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 18070 : 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 18070 : num_poses = 1;
149 18070 : if ( st_ivas->hSplitBinRend != NULL )
150 : {
151 964 : num_poses = st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses;
152 : }
153 :
154 18070 : output_Fs = st_ivas->hDecoderConfig->output_Fs;
155 18070 : nBins = st_ivas->hSpatParamRendCom->num_freq_bands;
156 18070 : renderer_type = st_ivas->renderer_type;
157 :
158 39100 : for ( pos_idx = 0; pos_idx < num_poses; pos_idx++ )
159 : {
160 21030 : hDiracDecBin = st_ivas->hDiracDecBin[pos_idx];
161 :
162 21030 : if ( hDiracDecBin == NULL )
163 : {
164 21030 : 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 21030 : hDiracDecBin->hTdDecorr = NULL;
170 21030 : hDiracDecBin->hReverb = NULL;
171 21030 : hDiracDecBin->h_freq_domain_decorr_ap_params = NULL;
172 21030 : hDiracDecBin->h_freq_domain_decorr_ap_state = NULL;
173 21030 : hDiracDecBin->phHrtfParambin = NULL;
174 : }
175 :
176 63090 : for ( j = 0; j < BINAURAL_CHANNELS; j++ )
177 : {
178 294420 : for ( k = 0; k < BINAURAL_CHANNELS + MAX_NUM_OBJECTS; k++ )
179 : {
180 252360 : set_zero( hDiracDecBin->processMtxRe[j][k], nBins );
181 252360 : set_zero( hDiracDecBin->processMtxIm[j][k], nBins );
182 : }
183 :
184 126180 : for ( k = 0; k < BINAURAL_CHANNELS; k++ )
185 : {
186 84120 : set_zero( hDiracDecBin->processMtxDecRe[j][k], nBins );
187 84120 : set_zero( hDiracDecBin->processMtxDecIm[j][k], nBins );
188 : }
189 42060 : set_zero( hDiracDecBin->ChEnePrev[j], nBins );
190 42060 : set_zero( hDiracDecBin->ChEneOutPrev[j], nBins );
191 : }
192 21030 : set_zero( hDiracDecBin->ChCrossRePrev, nBins );
193 21030 : set_zero( hDiracDecBin->ChCrossImPrev, nBins );
194 21030 : set_zero( hDiracDecBin->ChCrossReOutPrev, nBins );
195 21030 : set_zero( hDiracDecBin->ChCrossImOutPrev, nBins );
196 21030 : hDiracDecBin->renderStereoOutputInsteadOfBinaural = 0;
197 :
198 :
199 953970 : for ( bin = 0; bin < nBins; bin++ )
200 : {
201 932940 : 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 932940 : tmpFloat = max( 0.0f, 1.0f - binCenterFreq / 2700.0f );
204 932940 : hDiracDecBin->diffuseFieldCoherence[bin] = tmpFloat * sinf( binCenterFreq * EVS_PI / 550.0f ) / ( binCenterFreq * EVS_PI / 550.0f );
205 : }
206 :
207 210300 : for ( bin = 0; bin < BINAURAL_COHERENCE_DIFFERENCE_BINS; bin++ )
208 : {
209 189270 : hDiracDecBin->diffuseFieldCoherenceX[bin] = hDiracDecBin->diffuseFieldCoherence[bin] + diffuseFieldCoherenceDifferenceX[bin];
210 189270 : hDiracDecBin->diffuseFieldCoherenceY[bin] = hDiracDecBin->diffuseFieldCoherence[bin] + diffuseFieldCoherenceDifferenceY[bin];
211 189270 : hDiracDecBin->diffuseFieldCoherenceZ[bin] = hDiracDecBin->diffuseFieldCoherence[bin] + diffuseFieldCoherenceDifferenceZ[bin];
212 : }
213 :
214 21030 : if ( renderer_type == RENDERER_BINAURAL_PARAMETRIC ) /* Indication of binaural rendering without room effect */
215 : {
216 9698 : set_f( hDiracDecBin->earlyPartEneCorrection, 1.0f, CLDFB_NO_CHANNELS_MAX );
217 9698 : hDiracDecBin->hReverb = NULL;
218 : }
219 11332 : else if ( renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) /* Indication of binaural rendering with room effect */
220 : {
221 10323 : if ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR )
222 : {
223 5348 : mvr2r( ( *phHrtfParambin )->parametricEarlyPartEneCorrection, hDiracDecBin->earlyPartEneCorrection, nBins );
224 5348 : pRoomAcoustics = NULL;
225 : }
226 : else
227 : {
228 4975 : set_f( hDiracDecBin->earlyPartEneCorrection, 1.0f, CLDFB_NO_CHANNELS_MAX );
229 4975 : pRoomAcoustics = &( st_ivas->hRenderConfig->roomAcoustics );
230 : }
231 :
232 : /* reconfiguration needed when Reverb. parameters are changed -> close and open the handle again */
233 10323 : 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 10323 : if ( hDiracDecBin->hReverb == NULL && pos_idx == 0 ) /* open reverb only for the main direction */
240 : {
241 10323 : 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 10323 : ( *phHrtfParambin )->parametricReverberationTimes,
248 10323 : ( *phHrtfParambin )->parametricReverberationEneCorrections,
249 10323 : hDiracDecBin->earlyPartEneCorrection ) ) != IVAS_ERR_OK )
250 : {
251 0 : return error;
252 : }
253 : }
254 : }
255 1009 : else if ( renderer_type == RENDERER_STEREO_PARAMETRIC )
256 : {
257 1009 : set_f( hDiracDecBin->earlyPartEneCorrection, 1.0f, CLDFB_NO_CHANNELS_MAX );
258 1009 : hDiracDecBin->hReverb = NULL;
259 1009 : hDiracDecBin->renderStereoOutputInsteadOfBinaural = 1;
260 : }
261 : else /* Not valid renderer type for this renderer */
262 : {
263 0 : assert( false );
264 : }
265 :
266 21030 : hDiracDecBin->hDiffuseDist = NULL; /* Memory is allocated from stack during runtime when needed */
267 :
268 21030 : if ( hDiracDecBin->hTdDecorr == NULL )
269 : {
270 21030 : hDiracDecBin->useTdDecorr = 0;
271 : }
272 :
273 21030 : 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 21030 : if ( pos_idx == 0 ) /* open decorrelator only for the main direction */
279 : {
280 18070 : 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 18070 : if ( !hDiracDecBin->useTdDecorr && !( st_ivas->ivas_format == ISM_FORMAT && st_ivas->ism_mode == ISM_MODE_PARAM ) )
286 : {
287 8474 : ivas_dirac_dec_get_frequency_axis( frequency_axis, output_Fs, nBins );
288 :
289 8474 : if ( ( error = ivas_dirac_dec_decorr_open( &( hDiracDecBin->h_freq_domain_decorr_ap_params ),
290 8474 : &( 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 2960 : hDiracDecBin->useTdDecorr = st_ivas->hDiracDecBin[0]->useTdDecorr; /* copy the flag, but the implementation re-uses the decorrelated signal */
306 : }
307 :
308 21030 : hDiracDecBin->reqularizationFactor = configure_reqularization_factor( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate );
309 :
310 21030 : hDiracDecBin->phHrtfParambin = phHrtfParambin;
311 :
312 21030 : st_ivas->hDiracDecBin[pos_idx] = hDiracDecBin;
313 : }
314 :
315 : /* allocate transport channels */
316 18070 : if ( st_ivas->hTcBuffer == NULL )
317 : {
318 : int16_t nchan_to_allocate;
319 : int16_t n_samples_granularity;
320 :
321 7133 : nchan_to_allocate = BINAURAL_CHANNELS;
322 7133 : if ( st_ivas->hDiracDecBin[0] != NULL && st_ivas->hDiracDecBin[0]->useTdDecorr )
323 : {
324 1984 : nchan_to_allocate = 2 * BINAURAL_CHANNELS;
325 : }
326 5149 : else if ( st_ivas->hOutSetup.separateChannelEnabled )
327 : {
328 135 : nchan_to_allocate++;
329 : }
330 7133 : if ( st_ivas->ivas_format == MASA_ISM_FORMAT )
331 : {
332 3179 : nchan_to_allocate = BINAURAL_CHANNELS + st_ivas->nchan_ism;
333 : }
334 :
335 7133 : n_samples_granularity = ivas_jbm_dec_get_render_granularity( st_ivas->renderer_type, ivas_renderer_secondary_select( st_ivas ), output_Fs );
336 :
337 7133 : 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 18070 : return IVAS_ERR_OK;
343 : }
344 :
345 :
346 : /*-------------------------------------------------------------------------
347 : * ivas_dirac_dec_close_binaural_data()
348 : *
349 : * Close parametric binaural renderer
350 : *------------------------------------------------------------------------*/
351 :
352 151193 : 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 151193 : if ( hBinaural == NULL || *hBinaural == NULL )
359 : {
360 131787 : return;
361 : }
362 :
363 174654 : for ( pos_idx = 0; pos_idx < MAX_HEAD_ROT_POSES; pos_idx++ )
364 : {
365 155248 : if ( hBinaural[pos_idx] != NULL )
366 : {
367 22782 : if ( hBinaural[pos_idx]->hReverb != NULL )
368 : {
369 11163 : ivas_binaural_reverb_close( &( hBinaural[pos_idx]->hReverb ) );
370 : }
371 :
372 22782 : ivas_td_decorr_dec_close( &( hBinaural[pos_idx]->hTdDecorr ) );
373 :
374 22782 : if ( hBinaural[pos_idx]->h_freq_domain_decorr_ap_params != NULL )
375 : {
376 10125 : 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 22782 : free( hBinaural[pos_idx] );
380 22782 : hBinaural[pos_idx] = NULL;
381 : }
382 : }
383 :
384 19406 : 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 39493 : 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 39493 : if ( hHrtfParambin != NULL && *hHrtfParambin != NULL )
401 : {
402 : /* Tables already loaded from file */
403 28383 : return IVAS_ERR_OK;
404 : }
405 : else
406 : {
407 : /* Initialise tables from ROM */
408 : HRTFS_PARAMBIN *hrtfParambin;
409 :
410 11110 : 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 33330 : for ( i = 0; i < BINAURAL_CHANNELS; i++ )
416 : {
417 377740 : for ( j = 0; j < HRTF_SH_CHANNELS; j++ )
418 : {
419 355520 : mvr2r( hrtfShCoeffsRe[i][j], hrtfParambin->hrtfShCoeffsRe[i][j], HRTF_NUM_BINS );
420 355520 : mvr2r( hrtfShCoeffsIm[i][j], hrtfParambin->hrtfShCoeffsIm[i][j], HRTF_NUM_BINS );
421 : }
422 : }
423 :
424 11110 : mvr2r( parametricReverberationTimes, hrtfParambin->parametricReverberationTimes, CLDFB_NO_CHANNELS_MAX );
425 11110 : mvr2r( parametricReverberationEneCorrections, hrtfParambin->parametricReverberationEneCorrections, CLDFB_NO_CHANNELS_MAX );
426 11110 : mvr2r( parametricEarlyPartEneCorrection, hrtfParambin->parametricEarlyPartEneCorrection, CLDFB_NO_CHANNELS_MAX );
427 :
428 11110 : *hHrtfParambin = hrtfParambin;
429 :
430 11110 : return IVAS_ERR_OK;
431 : }
432 : }
433 :
434 :
435 : /*-------------------------------------------------------------------------
436 : * void ivas_dirac_dec_binaural_render()
437 : *
438 : *
439 : *------------------------------------------------------------------------*/
440 :
441 1590502 : 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 1590502 : hSpatParamRendCom = st_ivas->hSpatParamRendCom;
457 1590502 : nchan_out = BINAURAL_CHANNELS;
458 : #ifdef DEBUGGING
459 : assert( hSpatParamRendCom );
460 : #endif
461 4771506 : for ( ch = 0; ch < nchan_out; ch++ )
462 : {
463 3181004 : output_f_local[ch] = output_f[ch];
464 : }
465 1590502 : 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 1590502 : slots_to_render = min( hSpatParamRendCom->num_slots - hSpatParamRendCom->slots_rendered, nSamplesAsked / slot_size );
469 1590502 : *nSamplesRendered = slots_to_render * slot_size;
470 1590502 : first_sf = hSpatParamRendCom->subframes_rendered;
471 1590502 : last_sf = first_sf;
472 :
473 6042299 : while ( slots_to_render > 0 )
474 : {
475 4451797 : slots_to_render -= hSpatParamRendCom->subframe_nbslots[last_sf];
476 4451797 : last_sf++;
477 : }
478 :
479 : #ifdef DEBUGGING
480 : assert( slots_to_render == 0 );
481 : #endif
482 6042299 : for ( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ )
483 : {
484 4451797 : int16_t n_samples_sf = slot_size * hSpatParamRendCom->subframe_nbslots[subframe_idx];
485 4451797 : ivas_dirac_dec_binaural_internal( st_ivas, st_ivas->hCombinedOrientationData, output_f_local, nchan_transport, subframe_idx );
486 :
487 13355391 : for ( ch = 0; ch < nchan_out; ch++ )
488 : {
489 8903594 : output_f_local[ch] += n_samples_sf;
490 : }
491 :
492 : /* update combined orientation access index */
493 4451797 : ivas_combined_orientation_update_index( st_ivas->hCombinedOrientationData, n_samples_sf );
494 : }
495 :
496 1590502 : if ( hSpatParamRendCom->slots_rendered == hSpatParamRendCom->num_slots )
497 : {
498 1109114 : hSpatParamRendCom->dirac_read_idx = ( hSpatParamRendCom->dirac_read_idx + DEFAULT_JBM_SUBFRAMES_5MS ) % hSpatParamRendCom->dirac_md_buffer_length;
499 : }
500 :
501 1590502 : *nSamplesAvailable = ( hSpatParamRendCom->num_slots - hSpatParamRendCom->slots_rendered ) * slot_size;
502 :
503 1590502 : return;
504 : }
505 :
506 :
507 : /*-------------------------------------------------------------------------
508 : * ivas_dirac_dec_binaural_sba_gain()
509 : *
510 : * loudness correction for parametric binaural renderer
511 : *------------------------------------------------------------------------*/
512 :
513 536330 : 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 536330 : if ( nchan_remapped == 1 )
523 : {
524 243903 : gain = 1.4454f;
525 : }
526 : else
527 : {
528 292427 : gain = 1.3657f;
529 : }
530 :
531 1365087 : for ( n = 0; n < nchan_remapped; n++ )
532 : {
533 828757 : v_multc( output[n], gain, output[n], output_frame );
534 : }
535 :
536 536330 : return;
537 : }
538 :
539 :
540 : /*-------------------------------------------------------------------------
541 : * Local functions
542 : *------------------------------------------------------------------------*/
543 :
544 4451797 : 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 4451797 : hDiracDecBin = st_ivas->hDiracDecBin[0];
576 4451797 : assert( hDiracDecBin );
577 4451797 : hSpatParamRendCom = st_ivas->hSpatParamRendCom;
578 4451797 : nBins = hSpatParamRendCom->num_freq_bands;
579 4451797 : offsetSamples = hSpatParamRendCom->slots_rendered * nBins;
580 :
581 : /* Setup internal config */
582 4451797 : config_data.separateCenterChannelRendering = st_ivas->hOutSetup.separateChannelEnabled;
583 4451797 : config_data.ivas_format = st_ivas->ivas_format;
584 4451797 : config_data.mc_mode = st_ivas->mc_mode;
585 4451797 : config_data.ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate;
586 4451797 : config_data.nchan_transport = st_ivas->nchan_transport;
587 4451797 : config_data.qualityBasedSmFactor = st_ivas->hMasa != NULL ? st_ivas->hMasa->data.dir_decode_quality : 1.0f;
588 4451797 : config_data.processReverb = st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ? 1 : 0;
589 4451797 : if ( st_ivas->ivas_format == MASA_ISM_FORMAT )
590 : {
591 940470 : config_data.ism_mode = st_ivas->ism_mode;
592 : }
593 : else
594 : {
595 3511327 : config_data.ism_mode = ISM_MODE_NONE;
596 : }
597 :
598 : /* The input channel number at this processing function (not nchan_transport) */
599 4451797 : numInChannels = BINAURAL_CHANNELS;
600 4451797 : 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 341902 : numInChannels++;
603 : }
604 4109895 : 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 358488 : numInChannels += (uint8_t) st_ivas->nchan_ism;
607 : }
608 :
609 4451797 : Rmat[0][0] = 1.0f;
610 4451797 : Rmat[0][1] = 0.0f;
611 4451797 : Rmat[0][2] = 0.0f;
612 :
613 4451797 : Rmat[1][0] = 0.0f;
614 4451797 : Rmat[1][1] = 1.0f;
615 4451797 : Rmat[1][2] = 0.0f;
616 :
617 4451797 : Rmat[2][0] = 0.0f;
618 4451797 : Rmat[2][1] = 0.0f;
619 4451797 : Rmat[2][2] = 1.0f;
620 :
621 : /* CLDFB Analysis of input */
622 22200700 : for ( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ )
623 : {
624 57811004 : for ( ch = 0; ch < numInChannels; ch++ )
625 : {
626 40062101 : if ( ch == 0 || nchan_transport == 2 )
627 : {
628 32647907 : cldfbAnalysis_ts(
629 32647907 : &( st_ivas->hTcBuffer->tc[ch][nBins * slot + offsetSamples] ),
630 32647907 : Cldfb_RealBuffer_in[ch][slot],
631 32647907 : Cldfb_ImagBuffer_in[ch][slot],
632 : nBins, st_ivas->cldfbAnaDec[ch] );
633 : }
634 7414194 : 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 1007574 : mvr2r( Cldfb_RealBuffer_in[0][slot], Cldfb_RealBuffer_in[1][slot], nBins );
638 1007574 : 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 6406620 : if ( st_ivas->hSCE[0]->hCoreCoder[0] != NULL && st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag )
644 4917894 : {
645 : int16_t numCoreBands, b;
646 :
647 4917894 : numCoreBands = st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->numCoreBands;
648 :
649 9835788 : generate_masking_noise_dirac( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom,
650 : st_ivas->cldfbAnaDec[1],
651 4917894 : &st_ivas->hTcBuffer->tc[nchan_transport][hSpatParamRendCom->num_freq_bands * hSpatParamRendCom->slots_rendered],
652 4917894 : Cldfb_RealBuffer_in[2][slot], Cldfb_ImagBuffer_in[2][slot],
653 : slot,
654 4917894 : st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->hSCE[0]->hCoreCoder[0]->flag_cna,
655 4917894 : ( 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 9835788 : 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 4917894 : Cldfb_RealBuffer_in[1][slot], Cldfb_ImagBuffer_in[1][slot],
661 : slot,
662 4917894 : st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->hSCE[0]->hCoreCoder[0]->flag_cna,
663 4917894 : ( 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 96598462 : for ( b = 0; b < numCoreBands; b++ )
667 : {
668 91680568 : Cldfb_RealBuffer_in[0][slot][b] = INV_SQRT2 * ( Cldfb_RealBuffer_in[0][slot][b] + Cldfb_RealBuffer_in[2][slot][b] );
669 91680568 : Cldfb_RealBuffer_in[1][slot][b] = Cldfb_RealBuffer_in[0][slot][b];
670 91680568 : Cldfb_ImagBuffer_in[0][slot][b] = INV_SQRT2 * ( Cldfb_ImagBuffer_in[0][slot][b] + Cldfb_ImagBuffer_in[2][slot][b] );
671 91680568 : 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 136942646 : for ( ; b < nBins; b++ )
676 : {
677 132024752 : Cldfb_RealBuffer_in[0][slot][b] *= INV_SQRT2;
678 132024752 : 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 132024752 : Cldfb_RealBuffer_in[0][slot][b] += 0.5f * Cldfb_RealBuffer_in[2][slot][b];
680 :
681 132024752 : Cldfb_ImagBuffer_in[0][slot][b] *= INV_SQRT2;
682 132024752 : Cldfb_ImagBuffer_in[1][slot][b] = Cldfb_ImagBuffer_in[0][slot][b] + 0.5f * Cldfb_ImagBuffer_in[1][slot][b];
683 132024752 : 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 1488726 : v_multc( Cldfb_RealBuffer_in[0][slot], INV_SQRT_2, Cldfb_RealBuffer_in[0][slot], nBins );
691 1488726 : v_multc( Cldfb_ImagBuffer_in[0][slot], INV_SQRT_2, Cldfb_ImagBuffer_in[0][slot], nBins );
692 :
693 1488726 : mvr2r( Cldfb_RealBuffer_in[0][slot], Cldfb_RealBuffer_in[1][slot], nBins );
694 1488726 : mvr2r( Cldfb_ImagBuffer_in[0][slot], Cldfb_ImagBuffer_in[1][slot], nBins );
695 : }
696 : }
697 : }
698 :
699 17748903 : if ( hDiracDecBin->useTdDecorr )
700 : {
701 18760026 : for ( ch = BINAURAL_CHANNELS; ch < ( 2 * BINAURAL_CHANNELS ); ch++ )
702 : {
703 12506684 : cldfbAnalysis_ts(
704 12506684 : &( st_ivas->hTcBuffer->tc[ch][nBins * slot + offsetSamples] ),
705 12506684 : Cldfb_RealBuffer_in[ch][slot],
706 12506684 : Cldfb_ImagBuffer_in[ch][slot],
707 : nBins, st_ivas->cldfbAnaDec[ch] );
708 12506684 : if ( config_data.nchan_transport == 1 &&
709 10491536 : ( config_data.ivas_format == SBA_FORMAT || config_data.ivas_format == SBA_ISM_FORMAT ) )
710 : {
711 7805004 : v_multc( Cldfb_RealBuffer_in[ch][slot], INV_SQRT_2, Cldfb_RealBuffer_in[ch][slot], nBins );
712 7805004 : v_multc( Cldfb_ImagBuffer_in[ch][slot], INV_SQRT_2, Cldfb_ImagBuffer_in[ch][slot], nBins );
713 : }
714 : }
715 : }
716 : }
717 :
718 4451797 : if ( config_data.ivas_format == SBA_FORMAT || config_data.ivas_format == SBA_ISM_FORMAT )
719 : {
720 1918016 : hDiracDecBin->hDiffuseDist = &diffuseDistData;
721 :
722 1918016 : ivas_spar_param_to_masa_param_mapping( st_ivas, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, subframe );
723 1918016 : ivas_sba_prototype_renderer( st_ivas, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, subframe );
724 : }
725 :
726 4451797 : 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 750485 : ivas_omasa_preProcessStereoTransportsForEditedObjects( st_ivas, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, subframe );
729 : }
730 :
731 4451797 : if ( hCombinedOrientationData )
732 : {
733 3456380 : for ( i = 0; i < 3; i++ )
734 : {
735 10369140 : for ( j = 0; j < 3; j++ )
736 : {
737 7776855 : Rmat[i][j] = hCombinedOrientationData->Rmat[hCombinedOrientationData->subframe_idx][i][j];
738 : }
739 : }
740 :
741 864095 : 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 595056 : adaptTransportSignalsHeadtracked( hCombinedOrientationData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat );
745 :
746 595056 : 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 4451797 : if ( config_data.ivas_format == ISM_FORMAT )
751 : {
752 231908 : max_band_decorr = 0;
753 : }
754 4219889 : else if ( hDiracDecBin->useTdDecorr )
755 : {
756 1567151 : max_band_decorr = CLDFB_NO_CHANNELS_MAX;
757 : }
758 : else
759 : {
760 2652738 : max_band_decorr = hDiracDecBin->h_freq_domain_decorr_ap_params->max_band_decorr;
761 : }
762 :
763 4451797 : ivas_dirac_dec_binaural_formulate_input_covariance_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, subframe,
764 : subFrameTotalEne, IIReneLimiter );
765 :
766 4451797 : ivas_dirac_dec_binaural_formulate_target_covariance_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat, subframe,
767 4451797 : hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, subFrameTotalEne, IIReneLimiter, st_ivas->hMasaIsmData );
768 :
769 4451797 : nchanSeparateChannels = 0;
770 4451797 : 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 341902 : nchanSeparateChannels = 1;
773 : }
774 4109895 : 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 358488 : nchanSeparateChannels = (uint8_t) st_ivas->nchan_ism;
777 : }
778 :
779 4451797 : ivas_dirac_dec_binaural_determine_processing_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat, subframe,
780 4451797 : hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, nchanSeparateChannels, st_ivas->hMasaIsmData );
781 :
782 4451797 : pMultiBinPoseData = NULL;
783 4451797 : if ( st_ivas->hSplitBinRend != NULL )
784 : {
785 443184 : pMultiBinPoseData = &st_ivas->hSplitBinRend->splitrend.multiBinPoseData;
786 : }
787 :
788 4451797 : 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 443184 : ivas_dirac_dec_binaural_process_output( hDiracDecBin, hSpatParamRendCom, st_ivas->cldfbSynDec, output_f, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in,
791 443184 : max_band_decorr, numInChannels, config_data.processReverb, subframe, tmp_Cldfb_out_re, tmp_Cldfb_out_im,
792 : reverbRe, reverbIm, decorrRe, decorrIm, 1 );
793 :
794 1329552 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
795 : {
796 4386288 : for ( i = 0; i < hSpatParamRendCom->subframe_nbslots[subframe]; i++ )
797 : {
798 3499920 : 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 );
799 : }
800 : }
801 : }
802 : else
803 : {
804 4008613 : ivas_dirac_dec_binaural_process_output( hDiracDecBin, hSpatParamRendCom, st_ivas->cldfbSynDec, output_f, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in,
805 4008613 : max_band_decorr, numInChannels, config_data.processReverb, subframe, NULL, NULL,
806 : reverbRe, reverbIm, decorrRe, decorrIm, 1 );
807 : }
808 :
809 4451797 : hDiracDecBin->hDiffuseDist = NULL;
810 :
811 4451797 : if ( pMultiBinPoseData != NULL && pMultiBinPoseData->num_poses > 1 )
812 : {
813 : /* quaternion-based rotation from ivas_binRenderer_internal.c:ivas_binRenderer(), but using absolute rotation instead of delta rotations */
814 : IVAS_QUATERNION Quaternions_rot, Quaternions_abs, *Quaternions_ref;
815 : float Rmat_local[3][3];
816 :
817 314559 : if ( hCombinedOrientationData )
818 : {
819 314559 : Quaternions_ref = &hCombinedOrientationData->Quaternions[0];
820 314559 : Quaternions_rot.w = -3.0f; /* signal to use Euler */
821 314559 : Quaternions_abs.w = -3.0f; /* signal to use Euler */
822 314559 : Quat2EulerDegree( *Quaternions_ref, &Quaternions_abs.z, &Quaternions_abs.y, &Quaternions_abs.x ); /*order in Quat2Euler seems to be reversed ?*/
823 :
824 1675695 : for ( pos_idx = 1; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ )
825 : {
826 1361136 : Quaternions_rot.x = Quaternions_abs.x + pMultiBinPoseData->relative_head_poses[pos_idx][0];
827 1361136 : Quaternions_rot.y = Quaternions_abs.y + pMultiBinPoseData->relative_head_poses[pos_idx][1];
828 1361136 : Quaternions_rot.z = Quaternions_abs.z + pMultiBinPoseData->relative_head_poses[pos_idx][2];
829 :
830 1361136 : QuatToRotMat( Quaternions_rot, Rmat_local );
831 :
832 1361136 : hDiracDecBin = st_ivas->hDiracDecBin[pos_idx];
833 1361136 : assert( hDiracDecBin != NULL && "No DiracDecBin handle for this position" );
834 1361136 : if ( config_data.ivas_format == SBA_FORMAT || config_data.ivas_format == SBA_ISM_FORMAT )
835 : {
836 261872 : hDiracDecBin->hDiffuseDist = &diffuseDistData;
837 : }
838 :
839 : /* re-use input covariance for the side renderings */
840 4083408 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
841 : {
842 2722272 : mvr2r( st_ivas->hDiracDecBin[0]->ChEne[ch], hDiracDecBin->ChEne[ch], hSpatParamRendCom->num_freq_bands );
843 : }
844 1361136 : mvr2r( st_ivas->hDiracDecBin[0]->ChCrossRe, hDiracDecBin->ChCrossRe, hSpatParamRendCom->num_freq_bands );
845 1361136 : mvr2r( st_ivas->hDiracDecBin[0]->ChCrossIm, hDiracDecBin->ChCrossIm, hSpatParamRendCom->num_freq_bands );
846 :
847 1361136 : ivas_dirac_dec_binaural_formulate_target_covariance_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat_local, subframe, hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, subFrameTotalEne, IIReneLimiter, st_ivas->hMasaIsmData );
848 :
849 1361136 : ivas_dirac_dec_binaural_determine_processing_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat_local, subframe, hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, nchanSeparateChannels, st_ivas->hMasaIsmData );
850 :
851 : /* re-use reverb and decorr from main direction for the sides */
852 1361136 : ivas_dirac_dec_binaural_process_output( hDiracDecBin, hSpatParamRendCom, st_ivas->cldfbSynDec, output_f, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in,
853 1361136 : max_band_decorr, numInChannels, config_data.processReverb, subframe, tmp_Cldfb_out_re, tmp_Cldfb_out_im,
854 : reverbRe, reverbIm, decorrRe, decorrIm, 0 );
855 :
856 : /* copy from temporary buffer to the main split rendering buffer */
857 4083408 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
858 : {
859 13471712 : for ( i = 0; i < hSpatParamRendCom->subframe_nbslots[subframe]; i++ )
860 : {
861 10749440 : 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 );
862 : }
863 : }
864 :
865 1361136 : hDiracDecBin->hDiffuseDist = NULL;
866 : }
867 : }
868 : }
869 :
870 : /* update this counter only after the last rendering of split directions */
871 4451797 : hSpatParamRendCom->slots_rendered += hSpatParamRendCom->subframe_nbslots[subframe];
872 4451797 : hSpatParamRendCom->subframes_rendered++;
873 :
874 4451797 : return;
875 : }
876 :
877 :
878 13412110 : static void ivas_dirac_dec_decorrelate_slot(
879 : DIRAC_DEC_BIN_HANDLE hDiracDecBin,
880 : const int16_t num_freq_bands,
881 : const int16_t slot,
882 : float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
883 : float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
884 : float decRe[][CLDFB_NO_CHANNELS_MAX],
885 : float decIm[][CLDFB_NO_CHANNELS_MAX] )
886 : {
887 : int16_t offset, ch, bin;
888 : float onset_filter[BINAURAL_CHANNELS * CLDFB_NO_CHANNELS_MAX]; /* 2 ch, 60 bins */
889 : float decorrelatedFrameInterleaved[2 * BINAURAL_CHANNELS * CLDFB_NO_CHANNELS_MAX]; /* 2 ch, real + imag, 60 bins */
890 : float protoFrameF[2 * BINAURAL_CHANNELS * CLDFB_NO_CHANNELS_MAX]; /* 2 ch, real + imag, 60 bins */
891 13412110 : const int16_t protoIndexDir[BINAURAL_CHANNELS] = { 0, 1 };
892 :
893 : /* Decorrelation needs interleaved data. Copy left and right signals to proto_frame_f */
894 40236330 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
895 : {
896 26824220 : offset = num_freq_bands * BINAURAL_CHANNELS * ch;
897 1237939580 : for ( bin = 0; bin < num_freq_bands; bin++ )
898 : {
899 1211115360 : protoFrameF[( bin * BINAURAL_CHANNELS ) + offset] = inRe[ch][slot][bin];
900 1211115360 : protoFrameF[( bin * BINAURAL_CHANNELS ) + offset + 1] = inIm[ch][slot][bin];
901 : }
902 : }
903 :
904 : /* Decorrelate proto signal to decorrelatedFrameInterleaved */
905 13412110 : ivas_dirac_dec_decorr_process( num_freq_bands,
906 : BINAURAL_CHANNELS,
907 : BINAURAL_CHANNELS,
908 : DIRAC_SYNTHESIS_PSD_LS,
909 : BINAURAL_CHANNELS,
910 : protoFrameF,
911 : BINAURAL_CHANNELS,
912 : protoIndexDir,
913 : decorrelatedFrameInterleaved,
914 : onset_filter,
915 : hDiracDecBin->h_freq_domain_decorr_ap_params,
916 : hDiracDecBin->h_freq_domain_decorr_ap_state );
917 :
918 : /* De-interleave decorrelated signals*/
919 40236330 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
920 : {
921 26824220 : offset = num_freq_bands * BINAURAL_CHANNELS * ch;
922 1237939580 : for ( bin = 0; bin < num_freq_bands; bin++ )
923 : {
924 1211115360 : decRe[ch][bin] = decorrelatedFrameInterleaved[( bin * BINAURAL_CHANNELS ) + offset];
925 1211115360 : decIm[ch][bin] = decorrelatedFrameInterleaved[( bin * BINAURAL_CHANNELS ) + offset + 1];
926 : }
927 : }
928 :
929 13412110 : return;
930 : }
931 :
932 :
933 5160461 : static void ivas_dirac_dec_binaural_formulate_input_covariance_matrices(
934 : DIRAC_DEC_BIN_HANDLE hDiracDecBin,
935 : const SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom,
936 : const PARAMBIN_REND_CONFIG_HANDLE hConfig,
937 : float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
938 : float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
939 : const int16_t subframe,
940 : float *subFrameTotalEne,
941 : float *IIReneLimiter )
942 : {
943 : int16_t ch, slot, bin;
944 : int16_t nBins;
945 : float IIReneLimiterFactor;
946 : float qualityBasedSmFactor;
947 : float lowBitRateEQ[CLDFB_NO_CHANNELS_MAX];
948 : uint8_t applyLowBitRateEQ;
949 : IVAS_FORMAT ivas_format;
950 : int32_t ivas_total_brate;
951 : int16_t nchan_transport;
952 :
953 5160461 : ivas_format = hConfig->ivas_format;
954 5160461 : ivas_total_brate = hConfig->ivas_total_brate;
955 5160461 : nchan_transport = hConfig->nchan_transport;
956 5160461 : qualityBasedSmFactor = hConfig->qualityBasedSmFactor;
957 5160461 : qualityBasedSmFactor *= qualityBasedSmFactor;
958 5160461 : nBins = hSpatParamRendCom->num_freq_bands; /* Actually bins */
959 :
960 5160461 : set_zero( hDiracDecBin->ChCrossRe, nBins );
961 5160461 : set_zero( hDiracDecBin->ChCrossIm, nBins );
962 15481383 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
963 : {
964 10320922 : set_zero( hDiracDecBin->ChEne[ch], nBins );
965 : }
966 :
967 : /* Determine EQ for low bit rates (13.2 and 16.4 kbps) */
968 5160461 : applyLowBitRateEQ = 0;
969 5160461 : if ( ( ivas_format == MASA_FORMAT || ivas_format == MC_FORMAT ) && ivas_total_brate < MASA_STEREO_MIN_BITRATE )
970 : {
971 358791 : applyLowBitRateEQ = 1;
972 358791 : if ( ivas_total_brate == IVAS_16k4 )
973 : {
974 3617190 : for ( bin = 0; bin < LOW_BIT_RATE_BINAURAL_EQ_BINS; bin++ )
975 : {
976 3416235 : lowBitRateEQ[bin + LOW_BIT_RATE_BINAURAL_EQ_OFFSET] = lowBitRateBinauralEQ[bin] * 0.5f + 0.5f;
977 : }
978 : }
979 : else
980 : {
981 2841048 : for ( bin = 0; bin < LOW_BIT_RATE_BINAURAL_EQ_BINS; bin++ )
982 : {
983 2683212 : lowBitRateEQ[bin + LOW_BIT_RATE_BINAURAL_EQ_OFFSET] = lowBitRateBinauralEQ[bin];
984 : }
985 : }
986 : }
987 :
988 : /* Formulate input and target covariance matrices for this subframe */
989 5160461 : set_zero( subFrameTotalEne, CLDFB_NO_CHANNELS_MAX );
990 :
991 : /* Calculate input covariance matrix */
992 25744020 : for ( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ )
993 : {
994 940170979 : for ( bin = 0; bin < nBins; bin++ )
995 : {
996 2758762260 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
997 : {
998 : float instEne;
999 :
1000 1839174840 : instEne = ( inRe[ch][slot][bin] * inRe[ch][slot][bin] );
1001 1839174840 : instEne += ( inIm[ch][slot][bin] * inIm[ch][slot][bin] );
1002 1839174840 : hDiracDecBin->ChEne[ch][bin] += instEne;
1003 1839174840 : subFrameTotalEne[bin] += instEne;
1004 : }
1005 919587420 : hDiracDecBin->ChCrossRe[bin] += inRe[0][slot][bin] * inRe[1][slot][bin];
1006 919587420 : hDiracDecBin->ChCrossRe[bin] += inIm[0][slot][bin] * inIm[1][slot][bin];
1007 919587420 : hDiracDecBin->ChCrossIm[bin] += inRe[0][slot][bin] * inIm[1][slot][bin];
1008 919587420 : hDiracDecBin->ChCrossIm[bin] -= inIm[0][slot][bin] * inRe[1][slot][bin];
1009 : }
1010 : }
1011 :
1012 : /* Apply EQ at low bit rates */
1013 5160461 : if ( applyLowBitRateEQ )
1014 : {
1015 358791 : int16_t lastEqBin = LOW_BIT_RATE_BINAURAL_EQ_OFFSET + LOW_BIT_RATE_BINAURAL_EQ_BINS - 1;
1016 :
1017 6099447 : for ( bin = LOW_BIT_RATE_BINAURAL_EQ_OFFSET; bin < lastEqBin; bin++ )
1018 : {
1019 5740656 : subFrameTotalEne[bin] *= lowBitRateEQ[bin];
1020 : }
1021 6635501 : for ( ; bin < nBins; bin++ )
1022 : {
1023 6276710 : subFrameTotalEne[bin] *= lowBitRateEQ[lastEqBin];
1024 : }
1025 : }
1026 :
1027 5160461 : if ( ( ivas_format == SBA_FORMAT || ivas_format == SBA_ISM_FORMAT ) && nchan_transport == 2 )
1028 : {
1029 : float tempRe, tempIm;
1030 : float subFrameSumEne[CLDFB_NO_CHANNELS_MAX];
1031 :
1032 941810 : v_multc( subFrameTotalEne, SBA_CARDI_TARGET_ENERGY_GAIN, subFrameTotalEne, nBins );
1033 :
1034 941810 : set_zero( subFrameSumEne, CLDFB_NO_CHANNELS_MAX );
1035 4703804 : for ( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ )
1036 : {
1037 165464994 : for ( bin = 0; bin < nBins; bin++ )
1038 : {
1039 161703000 : tempRe = inRe[0][slot][bin] + inRe[1][slot][bin];
1040 161703000 : tempIm = inIm[0][slot][bin] + inIm[1][slot][bin];
1041 161703000 : subFrameSumEne[bin] += tempRe * tempRe + tempIm * tempIm;
1042 : }
1043 : }
1044 :
1045 41446250 : for ( bin = 0; bin < nBins; bin++ )
1046 : {
1047 40504440 : subFrameTotalEne[bin] = max( subFrameTotalEne[bin], subFrameSumEne[bin] );
1048 : }
1049 : }
1050 :
1051 : /* Temporal IIR-type smoothing of covariance matrices. Also apply encoding quality based smoothing factor. */
1052 5160461 : if ( ivas_format == MASA_FORMAT && ivas_total_brate < MASA_STEREO_MIN_BITRATE )
1053 : {
1054 298891 : IIReneLimiterFactor = 16.0f + ( 1.0f - qualityBasedSmFactor );
1055 : }
1056 : else
1057 : {
1058 4861570 : IIReneLimiterFactor = 8.0f + ( 1.0f - qualityBasedSmFactor );
1059 : }
1060 235867661 : for ( bin = 0; bin < nBins; bin++ )
1061 : {
1062 : float eneRatio;
1063 :
1064 : /* Temporally smooth cov mtx estimates for resulting mixing matrix stability. The design principle is that
1065 : * the energy history (IIR) must not be more than double of the current frame energy. This provides more
1066 : * robust performance at energy offsets when compared to typical IIR averaging. */
1067 230707200 : eneRatio = ( hDiracDecBin->ChEne[0][bin] + hDiracDecBin->ChEne[1][bin] ) / fmaxf( 1e-12f, ( hDiracDecBin->ChEnePrev[0][bin] + hDiracDecBin->ChEnePrev[1][bin] ) );
1068 230707200 : IIReneLimiter[bin] = fminf( 1.0f, eneRatio * IIReneLimiterFactor );
1069 :
1070 230707200 : hDiracDecBin->ChCrossRe[bin] *= qualityBasedSmFactor;
1071 230707200 : hDiracDecBin->ChCrossIm[bin] *= qualityBasedSmFactor;
1072 692121600 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1073 : {
1074 461414400 : hDiracDecBin->ChEne[ch][bin] *= qualityBasedSmFactor;
1075 : }
1076 :
1077 230707200 : hDiracDecBin->ChCrossRe[bin] += IIReneLimiter[bin] * hDiracDecBin->ChCrossRePrev[bin];
1078 230707200 : hDiracDecBin->ChCrossIm[bin] += IIReneLimiter[bin] * hDiracDecBin->ChCrossImPrev[bin];
1079 :
1080 692121600 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1081 : {
1082 461414400 : hDiracDecBin->ChEne[ch][bin] += IIReneLimiter[bin] * hDiracDecBin->ChEnePrev[ch][bin];
1083 : }
1084 :
1085 : /* Store energy values and coefficients for next round */
1086 230707200 : hDiracDecBin->ChCrossRePrev[bin] = hDiracDecBin->ChCrossRe[bin];
1087 230707200 : hDiracDecBin->ChCrossImPrev[bin] = hDiracDecBin->ChCrossIm[bin];
1088 692121600 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1089 : {
1090 461414400 : hDiracDecBin->ChEnePrev[ch][bin] = hDiracDecBin->ChEne[ch][bin];
1091 : }
1092 : }
1093 :
1094 5160461 : return;
1095 : }
1096 :
1097 :
1098 6697981 : static void ivas_dirac_dec_binaural_formulate_target_covariance_matrices(
1099 : DIRAC_DEC_BIN_HANDLE hDiracDecBin,
1100 : const SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom,
1101 : const PARAMBIN_REND_CONFIG_HANDLE hConfig,
1102 : float Rmat[3][3],
1103 : const int16_t subframe,
1104 : const int16_t isHeadtracked,
1105 : const float *subFrameTotalEne,
1106 : const float *IIReneLimiter,
1107 : const MASA_ISM_DATA_HANDLE hMasaIsmData )
1108 : {
1109 : int16_t ch, bin;
1110 : int16_t separateCenterChannelRendering;
1111 : int16_t nBins, idx;
1112 : float frameMeanDiffusenessEneWeight[CLDFB_NO_CHANNELS_MAX];
1113 : float qualityBasedSmFactor;
1114 : int16_t dirac_read_idx;
1115 : PARAMBIN_HRTF_GAIN_CACHE gainCache[MAX_GAIN_CACHE_SIZE];
1116 : IVAS_FORMAT ivas_format;
1117 : MC_MODE mc_mode;
1118 : int16_t gainCacheBaseIndex;
1119 :
1120 6697981 : separateCenterChannelRendering = hConfig->separateCenterChannelRendering;
1121 6697981 : ivas_format = hConfig->ivas_format;
1122 6697981 : mc_mode = hConfig->mc_mode;
1123 6697981 : qualityBasedSmFactor = hConfig->qualityBasedSmFactor;
1124 6697981 : qualityBasedSmFactor *= qualityBasedSmFactor;
1125 6697981 : nBins = hSpatParamRendCom->num_freq_bands; /* Actually bins */
1126 :
1127 6697981 : set_zero( hDiracDecBin->ChCrossReOut, nBins );
1128 6697981 : set_zero( hDiracDecBin->ChCrossImOut, nBins );
1129 20093943 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1130 : {
1131 13395962 : set_zero( hDiracDecBin->ChEneOut[ch], nBins );
1132 : }
1133 6697981 : set_zero( hDiracDecBin->frameMeanDiffuseness, nBins );
1134 :
1135 6697981 : set_zero( frameMeanDiffusenessEneWeight, CLDFB_NO_CHANNELS_MAX );
1136 :
1137 73677791 : for ( idx = 0; idx < MAX_GAIN_CACHE_SIZE; idx++ )
1138 : {
1139 66979810 : gainCache[idx].azi = -1000; /* Use -1000 as value for uninitialized cache. */
1140 : }
1141 :
1142 6697981 : dirac_read_idx = hSpatParamRendCom->render_to_md_map[subframe];
1143 :
1144 : /* Determine target covariance matrix containing target binaural properties */
1145 329656381 : for ( bin = 0; bin < nBins; bin++ )
1146 : {
1147 322958400 : float diffuseness = 1.0f; /* ratio1 and ratio2 are subtracted from diffuseness further below */
1148 322958400 : float diffusenessValForDecorrelationReduction = 1.0f;
1149 : float diffEneValForDecorrelationReduction;
1150 322958400 : float surCoh = 0.0f, spreadCoh = 0.0f; /* Default values if spreadSurroundCoherenceApplied == false */
1151 : float diffEne, dirEne, meanEnePerCh;
1152 : int16_t dirIndex;
1153 :
1154 : /* When BINAURAL_ROOM is not indicated, hBinaural->earlyPartEneCorrection[bin] values are all 1.0f.
1155 : * When BINAURAL_ROOM is indicated, the binaural audio output is based on combined use of the
1156 : * HRTF data set and a BRIR-based data set. The HRTF data set is spectrally corrected to match
1157 : * the early spectrum of the BRIR data, using the spectral correction data in
1158 : * hBinaural->earlyPartEneCorrection[bin], based on the BRIR set. */
1159 322958400 : meanEnePerCh = hDiracDecBin->earlyPartEneCorrection[bin] * subFrameTotalEne[bin] / 2.0f;
1160 :
1161 : /* Determine direct part target covariance matrix (for 1 or 2 directions) */
1162 755576040 : for ( dirIndex = 0; dirIndex < hSpatParamRendCom->numSimultaneousDirections; dirIndex++ )
1163 : {
1164 : int16_t aziDeg, eleDeg;
1165 : float lRealp, lImagp, rRealp, rImagp;
1166 : float lRealpTmp, lImagpTmp, rRealpTmp, rImagpTmp;
1167 : float hrtfEne[BINAURAL_CHANNELS], hrtfCrossRe, hrtfCrossIm, ratio;
1168 432617640 : uint8_t isIsmDirection = 0;
1169 :
1170 432617640 : if ( dirIndex == 0 ) /* For first of the two simultaneous directions */
1171 : {
1172 322958400 : aziDeg = hSpatParamRendCom->azimuth[dirac_read_idx][bin];
1173 322958400 : eleDeg = hSpatParamRendCom->elevation[dirac_read_idx][bin];
1174 322958400 : ratio = hSpatParamRendCom->energy_ratio1[dirac_read_idx][bin];
1175 322958400 : spreadCoh = hSpatParamRendCom->spreadCoherence[dirac_read_idx][bin];
1176 322958400 : gainCacheBaseIndex = 0;
1177 : }
1178 109659240 : else if ( ivas_format != MASA_ISM_FORMAT || ( ivas_format == MASA_ISM_FORMAT && dirIndex < hSpatParamRendCom->numParametricDirections ) ) /* For second of the two simultaneous directions */
1179 : {
1180 61572480 : if ( ( ratio = hSpatParamRendCom->energy_ratio2[dirac_read_idx][bin] ) < 0.001 )
1181 : {
1182 : /* This touches only MASA path where second direction always has smaller ratio and
1183 : * for non-2dir it is zero. As the whole direction contribution is multiplied with
1184 : * the ratio, a very small ratio does not contribute any energy to output. Thus,
1185 : * it is better to save complexity. */
1186 26837150 : continue;
1187 : }
1188 34735330 : aziDeg = hSpatParamRendCom->azimuth2[dirac_read_idx][bin];
1189 34735330 : eleDeg = hSpatParamRendCom->elevation2[dirac_read_idx][bin];
1190 34735330 : spreadCoh = hSpatParamRendCom->spreadCoherence2[dirac_read_idx][bin];
1191 34735330 : gainCacheBaseIndex = 3;
1192 : }
1193 : else /* For object directions of MASA_ISM_FORMAT */
1194 : {
1195 48086760 : isIsmDirection = 1;
1196 : uint16_t ismDirIndex;
1197 48086760 : ismDirIndex = dirIndex - hSpatParamRendCom->numParametricDirections;
1198 48086760 : assert( hMasaIsmData != NULL && "hMasaIsmData should not be NULL if we use it" );
1199 :
1200 48086760 : if ( hMasaIsmData->ism_dir_is_edited[ismDirIndex] )
1201 : {
1202 3208320 : aziDeg = hMasaIsmData->azimuth_ism_edited[ismDirIndex];
1203 3208320 : eleDeg = hMasaIsmData->elevation_ism_edited[ismDirIndex];
1204 : }
1205 : else
1206 : {
1207 44878440 : aziDeg = hMasaIsmData->azimuth_ism[ismDirIndex][dirac_read_idx];
1208 44878440 : eleDeg = hMasaIsmData->elevation_ism[ismDirIndex][dirac_read_idx];
1209 : }
1210 48086760 : ratio = hMasaIsmData->energy_ratio_ism[ismDirIndex][dirac_read_idx][bin];
1211 48086760 : spreadCoh = 0.0f;
1212 48086760 : gainCacheBaseIndex = 6 + ismDirIndex;
1213 : }
1214 :
1215 405780490 : diffuseness -= ratio; /* diffuseness = 1 - ratio1 - ratio2 */
1216 :
1217 405780490 : if ( diffuseness < 0.0f )
1218 : {
1219 800689 : diffuseness = 0.0f;
1220 : }
1221 405780490 : if ( isIsmDirection )
1222 : {
1223 : /* Objects cause lesser decorrelation reduction, to avoid removing all decorrelation when only objects are present */
1224 48086760 : diffusenessValForDecorrelationReduction -= ratio * 0.5f;
1225 : }
1226 : else
1227 : {
1228 357693730 : diffusenessValForDecorrelationReduction -= ratio;
1229 : }
1230 :
1231 405780490 : if ( separateCenterChannelRendering )
1232 : {
1233 : /* In masa + mono rendering mode, the center directions originate from phantom sources, so the
1234 : * spread coherence is increased */
1235 : float aziRad, eleRad, doaVectorX, spatialAngleDeg, altSpreadCoh;
1236 :
1237 1117800 : aziRad = (float) aziDeg * PI_OVER_180;
1238 1117800 : eleRad = (float) eleDeg * PI_OVER_180;
1239 1117800 : doaVectorX = cosf( aziRad ) * cosf( eleRad );
1240 1117800 : spatialAngleDeg = acosf( doaVectorX ) * _180_OVER_PI;
1241 1117800 : altSpreadCoh = 1.0f - ( spatialAngleDeg / 30.0f );
1242 1117800 : spreadCoh = max( spreadCoh, altSpreadCoh );
1243 : }
1244 :
1245 405780490 : getDirectPartGains( bin, aziDeg, eleDeg, &lRealp, &lImagp, &rRealp, &rImagp, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache[gainCacheBaseIndex], isHeadtracked, *hDiracDecBin->phHrtfParambin );
1246 :
1247 405780490 : if ( hDiracDecBin->renderStereoOutputInsteadOfBinaural )
1248 : {
1249 : /* Synthesizing spread coherence is not needed for stereo loudspeaker output,
1250 : * as directional sound is reproduced with two loudspeakers in any case */
1251 22320197 : spreadCoh = 0.0f;
1252 : }
1253 :
1254 405780490 : if ( spreadCoh > 0.0f )
1255 : {
1256 : float centerMul, sidesMul;
1257 : float hrtfEneCenter, hrtfEneSides, hrtfEneRealized, eneCorrectionFactor;
1258 : float w1, w2, w3, eq;
1259 :
1260 107204532 : hrtfEneCenter = ( lRealp * lRealp ) + ( lImagp * lImagp ) + ( rRealp * rRealp ) + ( rImagp * rImagp );
1261 :
1262 : /* Spread coherence is synthesized as coherent sources at 30 degree horizontal spacing.
1263 : * The following formulas determine the gains for these sources.
1264 : * spreadCoh = 0: Only panning
1265 : * spreadCoh = 0.5: Three sources coherent panning (e.g. 30 0 -30 deg azi)
1266 : * spreadCoh = 1.0: Two sources coherent panning with gap (as above, but center is silent) */
1267 107204532 : if ( spreadCoh < 0.5f )
1268 : {
1269 : /* 0.0f < spreadCoh < 0.5f */
1270 98212038 : sidesMul = 0.5774f * spreadCoh * 2.0f; /* sqrt(1/3) = 0.5774f */
1271 98212038 : centerMul = 1.0f - ( spreadCoh * 2.0f ) + sidesMul;
1272 : }
1273 : else
1274 : {
1275 : /* 0.5f <= spreadCoh < 1.0f */
1276 8992494 : centerMul = 2.0f - ( 2.0f * spreadCoh );
1277 8992494 : sidesMul = inv_sqrt( centerMul + 2.0f );
1278 8992494 : centerMul *= sidesMul;
1279 : }
1280 :
1281 : /* Apply the gain for the center source of the three coherent sources */
1282 107204532 : lRealp *= centerMul;
1283 107204532 : lImagp *= centerMul;
1284 107204532 : rRealp *= centerMul;
1285 107204532 : rImagp *= centerMul;
1286 :
1287 : /* Apply the gain for the left source of the three coherent sources */
1288 107204532 : getDirectPartGains( bin, aziDeg + 30, eleDeg, &lRealpTmp, &lImagpTmp, &rRealpTmp, &rImagpTmp, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache[gainCacheBaseIndex + 1], isHeadtracked, *hDiracDecBin->phHrtfParambin );
1289 :
1290 107204532 : hrtfEneSides = ( lRealpTmp * lRealpTmp ) + ( lImagpTmp * lImagpTmp ) + ( rRealpTmp * rRealpTmp ) + ( rImagpTmp * rImagpTmp );
1291 107204532 : lRealp += sidesMul * lRealpTmp;
1292 107204532 : lImagp += sidesMul * lImagpTmp;
1293 107204532 : rRealp += sidesMul * rRealpTmp;
1294 107204532 : rImagp += sidesMul * rImagpTmp;
1295 :
1296 : /* Apply the gain for the right source of the three coherent sources.
1297 : * -30 degrees to 330 wrapping due to internal functions. */
1298 107204532 : getDirectPartGains( bin, aziDeg + 330, eleDeg, &lRealpTmp, &lImagpTmp, &rRealpTmp, &rImagpTmp, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache[gainCacheBaseIndex + 2], isHeadtracked, *hDiracDecBin->phHrtfParambin );
1299 107204532 : hrtfEneSides += ( lRealpTmp * lRealpTmp ) + ( lImagpTmp * lImagpTmp ) + ( rRealpTmp * rRealpTmp ) + ( rImagpTmp * rImagpTmp );
1300 107204532 : lRealp += sidesMul * lRealpTmp;
1301 107204532 : lImagp += sidesMul * lImagpTmp;
1302 107204532 : rRealp += sidesMul * rRealpTmp;
1303 107204532 : rImagp += sidesMul * rImagpTmp;
1304 :
1305 : /* Formulate an eneCorrectionFactor that compensates for the coherent summation of the HRTFs */
1306 107204532 : hrtfEneRealized = ( lRealp * lRealp ) + ( lImagp * lImagp ) + ( rRealp * rRealp ) + ( rImagp * rImagp );
1307 214409064 : eneCorrectionFactor = ( ( hrtfEneSides * sidesMul * sidesMul ) +
1308 107204532 : ( hrtfEneCenter * centerMul * centerMul ) ) /
1309 107204532 : max( 1e-12f, hrtfEneRealized );
1310 :
1311 : /* Weighting factors to determine appropriate target spectrum for spread coherent sound */
1312 107204532 : if ( spreadCoh < 0.5 )
1313 : {
1314 98212038 : w1 = 1.0f - 2.0f * spreadCoh;
1315 98212038 : w2 = 2.0f * spreadCoh;
1316 98212038 : w3 = 0.0f;
1317 : }
1318 : else
1319 : {
1320 8992494 : w1 = 0.0f;
1321 8992494 : w2 = 2.0f - 2.0f * spreadCoh;
1322 8992494 : w3 = 2.0f * spreadCoh - 1.0f;
1323 : }
1324 :
1325 107204532 : if ( ( ivas_format == MC_FORMAT && mc_mode == MC_MODE_MCMASA ) )
1326 : {
1327 5476237 : idx = min( bin, MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS - 1 );
1328 :
1329 : /* Apply the target spectrum to the eneCorrectionFactor */
1330 5476237 : if ( separateCenterChannelRendering ) /* spreadCoh mostly originates from phantom sources in separate channel rendering mode */
1331 : {
1332 666984 : eneCorrectionFactor *= w1 * 1.0f + ( w2 + w3 ) * spreadCohEne1[idx];
1333 : }
1334 : else
1335 : {
1336 4809253 : eneCorrectionFactor *= w1 * 1.0f + w2 * spreadCohEne05[idx] + w3 * spreadCohEne1[idx];
1337 : }
1338 : }
1339 :
1340 : /* Equalize the spread coherent combined HRTFs */
1341 107204532 : eq = min( 4.0f, sqrtf( eneCorrectionFactor ) );
1342 107204532 : lRealp *= eq;
1343 107204532 : lImagp *= eq;
1344 107204532 : rRealp *= eq;
1345 107204532 : rImagp *= eq;
1346 : }
1347 :
1348 405780490 : hrtfEne[0] = ( lRealp * lRealp ) + ( lImagp * lImagp );
1349 405780490 : hrtfEne[1] = ( rRealp * rRealp ) + ( rImagp * rImagp );
1350 405780490 : hrtfCrossRe = ( lRealp * rRealp ) + ( lImagp * rImagp );
1351 405780490 : hrtfCrossIm = ( -lImagp * rRealp ) + ( lRealp * rImagp );
1352 :
1353 : /* Add direct part (1 or 2) covariance matrix */
1354 405780490 : dirEne = ratio * meanEnePerCh;
1355 405780490 : hDiracDecBin->ChEneOut[0][bin] += dirEne * hrtfEne[0]; /* Dir ene part*/
1356 405780490 : hDiracDecBin->ChEneOut[1][bin] += dirEne * hrtfEne[1];
1357 405780490 : hDiracDecBin->ChCrossReOut[bin] += dirEne * hrtfCrossRe; /* Dir cross re */
1358 405780490 : hDiracDecBin->ChCrossImOut[bin] += dirEne * hrtfCrossIm; /* Dir cross im */
1359 : }
1360 :
1361 : /* Add diffuse / ambient part covariance matrix */
1362 322958400 : diffuseness = max( 0.0f, diffuseness );
1363 322958400 : diffEne = diffuseness * meanEnePerCh;
1364 322958400 : surCoh = hSpatParamRendCom->surroundingCoherence[dirac_read_idx][bin];
1365 :
1366 322958400 : diffusenessValForDecorrelationReduction = max( 0.0f, diffusenessValForDecorrelationReduction );
1367 322958400 : diffEneValForDecorrelationReduction = diffusenessValForDecorrelationReduction * meanEnePerCh;
1368 :
1369 322958400 : if ( ( ivas_format == MC_FORMAT && mc_mode == MC_MODE_MCMASA ) )
1370 : {
1371 10222740 : if ( !hDiracDecBin->renderStereoOutputInsteadOfBinaural )
1372 : {
1373 : float spectrumModVal;
1374 :
1375 10222740 : idx = min( bin, MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS - 1 );
1376 : /* Apply target spectrum that emphasizes low frequencies when the sound is surround coherent */
1377 10222740 : spectrumModVal = ( 1.0f - surCoh ) + surCoh * surCohEne[idx];
1378 10222740 : diffEne *= spectrumModVal;
1379 :
1380 : /* Modify also the value for decorrelation reduction */
1381 10222740 : diffEneValForDecorrelationReduction *= spectrumModVal;
1382 : }
1383 : }
1384 322958400 : hDiracDecBin->ChEneOut[0][bin] += diffEne; /* Diff ene part*/
1385 322958400 : hDiracDecBin->ChEneOut[1][bin] += diffEne;
1386 :
1387 322958400 : if ( hDiracDecBin->renderStereoOutputInsteadOfBinaural )
1388 : {
1389 : /* When rendering stereo, ambience (except for surround coherent sound) has zero ICC. */
1390 16781340 : hDiracDecBin->ChCrossReOut[bin] += surCoh * diffEne;
1391 : }
1392 : else /* When rendering binaural, ambience has frequency dependent ICC. */
1393 : {
1394 306177060 : if ( ( ivas_format == SBA_FORMAT || ivas_format == SBA_ISM_FORMAT ) && bin < BINAURAL_COHERENCE_DIFFERENCE_BINS )
1395 19618992 : {
1396 : float diffuseFieldCoherence;
1397 19618992 : diffuseFieldCoherence = hDiracDecBin->hDiffuseDist->diffuseRatioX[bin] * hDiracDecBin->diffuseFieldCoherenceX[bin] + hDiracDecBin->hDiffuseDist->diffuseRatioY[bin] * hDiracDecBin->diffuseFieldCoherenceY[bin] + hDiracDecBin->hDiffuseDist->diffuseRatioZ[bin] * hDiracDecBin->diffuseFieldCoherenceZ[bin];
1398 19618992 : hDiracDecBin->ChCrossReOut[bin] += ( ( 1.0f - surCoh ) * diffuseFieldCoherence + surCoh ) * diffEne;
1399 : }
1400 : else
1401 : {
1402 286558068 : hDiracDecBin->ChCrossReOut[bin] += ( ( 1.0f - surCoh ) * hDiracDecBin->diffuseFieldCoherence[bin] + surCoh ) * diffEne;
1403 : }
1404 : }
1405 :
1406 : /* Store parameters for formulating average diffuseness over frame */
1407 322958400 : hDiracDecBin->frameMeanDiffuseness[bin] += diffEneValForDecorrelationReduction;
1408 322958400 : frameMeanDiffusenessEneWeight[bin] += meanEnePerCh;
1409 : }
1410 :
1411 : /* Formulate average diffuseness over frame */
1412 329656381 : for ( bin = 0; bin < nBins; bin++ )
1413 : {
1414 322958400 : hDiracDecBin->frameMeanDiffuseness[bin] /= fmaxf( 1e-12f, frameMeanDiffusenessEneWeight[bin] );
1415 : }
1416 :
1417 329656381 : for ( bin = 0; bin < nBins; bin++ )
1418 : {
1419 322958400 : hDiracDecBin->ChCrossReOut[bin] *= qualityBasedSmFactor;
1420 322958400 : hDiracDecBin->ChCrossImOut[bin] *= qualityBasedSmFactor;
1421 :
1422 968875200 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1423 : {
1424 645916800 : hDiracDecBin->ChEneOut[ch][bin] *= qualityBasedSmFactor;
1425 : }
1426 :
1427 322958400 : hDiracDecBin->ChCrossReOut[bin] += IIReneLimiter[bin] * hDiracDecBin->ChCrossReOutPrev[bin];
1428 322958400 : hDiracDecBin->ChCrossImOut[bin] += IIReneLimiter[bin] * hDiracDecBin->ChCrossImOutPrev[bin];
1429 :
1430 968875200 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1431 : {
1432 645916800 : hDiracDecBin->ChEneOut[ch][bin] += IIReneLimiter[bin] * hDiracDecBin->ChEneOutPrev[ch][bin];
1433 : }
1434 :
1435 : /* Store energy values and coefficients for next round */
1436 322958400 : hDiracDecBin->ChCrossReOutPrev[bin] = hDiracDecBin->ChCrossReOut[bin];
1437 322958400 : hDiracDecBin->ChCrossImOutPrev[bin] = hDiracDecBin->ChCrossImOut[bin];
1438 :
1439 968875200 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1440 : {
1441 645916800 : hDiracDecBin->ChEneOutPrev[ch][bin] = hDiracDecBin->ChEneOut[ch][bin];
1442 : }
1443 : }
1444 :
1445 6697981 : return;
1446 : }
1447 :
1448 6697981 : static void ivas_dirac_dec_binaural_determine_processing_matrices(
1449 : DIRAC_DEC_BIN_HANDLE hDiracDecBin,
1450 : SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom,
1451 : PARAMBIN_REND_CONFIG_HANDLE hConfig,
1452 : const int16_t max_band_decorr,
1453 : float Rmat[3][3],
1454 : const int16_t subframe,
1455 : const int16_t isHeadtracked,
1456 : const int16_t nchanSeparateChannels,
1457 : const MASA_ISM_DATA_HANDLE hMasaIsmData )
1458 : {
1459 : int16_t chA, chB, bin;
1460 : int16_t separateCenterChannelRendering;
1461 : int16_t nBins;
1462 : int16_t dirac_read_idx;
1463 : PARAMBIN_HRTF_GAIN_CACHE gainCache[MAX_NUM_OBJECTS];
1464 : int16_t idx;
1465 : ISM_MODE ism_mode;
1466 : IVAS_FORMAT ivas_format;
1467 : MC_MODE mc_mode;
1468 : int32_t ivas_total_brate;
1469 : int16_t nchan_transport;
1470 :
1471 6697981 : ivas_format = hConfig->ivas_format;
1472 6697981 : separateCenterChannelRendering = nchanSeparateChannels > 0;
1473 6697981 : mc_mode = hConfig->mc_mode;
1474 6697981 : ivas_total_brate = hConfig->ivas_total_brate;
1475 6697981 : nchan_transport = hConfig->nchan_transport;
1476 6697981 : nBins = hSpatParamRendCom->num_freq_bands; /* Actually bins */
1477 :
1478 6697981 : ism_mode = hConfig->ism_mode;
1479 :
1480 6697981 : dirac_read_idx = hSpatParamRendCom->render_to_md_map[subframe];
1481 :
1482 33489905 : for ( idx = 0; idx < MAX_NUM_OBJECTS; idx++ )
1483 : {
1484 26791924 : gainCache[idx].azi = -1000; /* Use -1000 as value for uninitialized cache. */
1485 : }
1486 :
1487 329656381 : for ( bin = 0; bin < nBins; bin++ )
1488 : {
1489 : float tmpMtxRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], tmpMtxIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS], resultMtxRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], resultMtxIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS], gain;
1490 : float CxRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], CxIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; /* Input covariance matrix */
1491 : float realizedOutputEne, targetOutputEne, missingOutputEne;
1492 : float CrEneL, CrEneR; /* Cr = residual decorrelated sound covariance matrix */
1493 : float CrCrossRe, CrCrossIm;
1494 : 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 */
1495 322958400 : float prototypeMtx[BINAURAL_CHANNELS][BINAURAL_CHANNELS] = { { 1.0f, 0.05f }, { 0.05f, 1.0f } }; /* Prototype matrix determines a reference signal in mixing matrix determination */
1496 :
1497 322958400 : CrEneL = 0.0f;
1498 322958400 : CrEneR = 0.0f;
1499 :
1500 : /* Formulate main processing matrix M */
1501 322958400 : formulate2x2MixingMatrix( hDiracDecBin->ChEne[0][bin], hDiracDecBin->ChEne[1][bin],
1502 : hDiracDecBin->ChCrossRe[bin], hDiracDecBin->ChCrossIm[bin],
1503 : hDiracDecBin->ChEneOut[0][bin], hDiracDecBin->ChEneOut[1][bin],
1504 : hDiracDecBin->ChCrossReOut[bin], hDiracDecBin->ChCrossImOut[bin],
1505 : prototypeMtx, Mre, Mim, hDiracDecBin->reqularizationFactor );
1506 :
1507 : /* Load estimated covariance matrix to the [2][2] matrix form */
1508 322958400 : CxRe[0][0] = hDiracDecBin->ChEne[0][bin];
1509 322958400 : CxRe[1][1] = hDiracDecBin->ChEne[1][bin];
1510 322958400 : CxRe[1][0] = hDiracDecBin->ChCrossRe[bin];
1511 322958400 : CxRe[0][1] = hDiracDecBin->ChCrossRe[bin];
1512 322958400 : CxIm[0][0] = 0.0f;
1513 322958400 : CxIm[1][1] = 0.0f;
1514 322958400 : CxIm[1][0] = hDiracDecBin->ChCrossIm[bin];
1515 322958400 : CxIm[0][1] = -hDiracDecBin->ChCrossIm[bin];
1516 :
1517 : /* Make matrix multiplication M*Cx*M' to determine resulting covariance matrix of processing input with M */
1518 322958400 : matrixMul( Mre, Mim, CxRe, CxIm, tmpMtxRe, tmpMtxIm );
1519 322958400 : matrixTransp2Mul( tmpMtxRe, tmpMtxIm, Mre, Mim, resultMtxRe, resultMtxIm );
1520 :
1521 : /* When below the frequency limit where decorrelation is applied, we inject the decorrelated
1522 : * residual (or missing) signal component. The procedure is active when there are not enough independent
1523 : * signal energy to synthesize a signal with the target covariance matrix from the non-decorrelated signals */
1524 322958400 : if ( bin < max_band_decorr )
1525 : {
1526 : float decorrelationReductionFactor;
1527 :
1528 : /* Subtract the resulting covariance matrix from the target covariance matrix to determine
1529 : * what signal component is missing. The result is the target covariance matrix for the residual signal, i.e.,
1530 : * a residual covariance matrix. */
1531 152708670 : CrEneL = max( 0.0f, hDiracDecBin->ChEneOut[0][bin] - resultMtxRe[0][0] );
1532 152708670 : CrEneR = max( 0.0f, hDiracDecBin->ChEneOut[1][bin] - resultMtxRe[1][1] );
1533 152708670 : CrCrossRe = hDiracDecBin->ChCrossReOut[bin] - resultMtxRe[1][0];
1534 152708670 : CrCrossIm = hDiracDecBin->ChCrossImOut[bin] - resultMtxIm[1][0];
1535 :
1536 : /* The amount of the decorrelated sound is further controlled based on the spatial metadata,
1537 : * by determining an energy-suppressed residual covariance matrix that is a control parameter
1538 : * that guides the processing of the decorrelated sound to a residual signal.
1539 : * The procedure improves quality in e.g. double-talk 2-direction rendering situations.*/
1540 152708670 : if ( ivas_format == MASA_FORMAT && ivas_total_brate < MASA_STEREO_MIN_BITRATE )
1541 : {
1542 24872340 : decorrelationReductionFactor = 1.0f;
1543 : }
1544 127836330 : else if ( ( ivas_format == MC_FORMAT && mc_mode == MC_MODE_MCMASA ) || ( ivas_format == MASA_FORMAT && nchan_transport == 1 ) )
1545 : {
1546 32720310 : decorrelationReductionFactor = sqrtf( fmaxf( 0.0f, hDiracDecBin->frameMeanDiffuseness[bin] ) );
1547 : }
1548 95116020 : else if ( ( ivas_format == SBA_FORMAT || ivas_format == SBA_ISM_FORMAT ) && nchan_transport == 1 )
1549 : {
1550 38624280 : decorrelationReductionFactor = 1.0f;
1551 : }
1552 : else
1553 : {
1554 56491740 : decorrelationReductionFactor = fmaxf( 0.0f, hDiracDecBin->frameMeanDiffuseness[bin] );
1555 : }
1556 152708670 : CrEneL *= decorrelationReductionFactor;
1557 152708670 : CrEneR *= decorrelationReductionFactor;
1558 152708670 : CrCrossRe *= decorrelationReductionFactor;
1559 152708670 : CrCrossIm *= decorrelationReductionFactor;
1560 :
1561 : /* Determine a residual mixing matrix Mdec for processing the decorrelated signal to obtain
1562 : * the residual signal (that has the residual covariance matrix) */
1563 152708670 : formulate2x2MixingMatrix( hDiracDecBin->ChEne[0][bin], hDiracDecBin->ChEne[1][bin],
1564 : 0.0f, 0.0f, /* Decorrelated signal has ideally no cross-terms */
1565 : CrEneL, CrEneR,
1566 : CrCrossRe, CrCrossIm,
1567 : prototypeMtx, MdecRe, MdecIm, 0.2f );
1568 : }
1569 : else
1570 : {
1571 510749190 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
1572 : {
1573 340499460 : set_zero( MdecRe[chA], BINAURAL_CHANNELS );
1574 340499460 : set_zero( MdecIm[chA], BINAURAL_CHANNELS );
1575 : }
1576 : }
1577 :
1578 : /* The regularizations at determining mixing matrices cause signal energy to be lost to some degree, which is compensated for here */
1579 322958400 : realizedOutputEne = CrEneL + CrEneR + resultMtxRe[0][0] + resultMtxRe[1][1];
1580 322958400 : targetOutputEne = hDiracDecBin->ChEneOut[0][bin] + hDiracDecBin->ChEneOut[1][bin];
1581 322958400 : missingOutputEne = fmaxf( 0.0f, targetOutputEne - realizedOutputEne );
1582 :
1583 322958400 : gain = sqrtf( ( resultMtxRe[0][0] + resultMtxRe[1][1] + missingOutputEne ) /
1584 322958400 : fmaxf( 1e-12f, resultMtxRe[0][0] + resultMtxRe[1][1] ) );
1585 322958400 : gain = fminf( 4.0f, gain );
1586 :
1587 968875200 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
1588 : {
1589 1937750400 : for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
1590 : {
1591 1291833600 : Mre[chA][chB] *= gain;
1592 1291833600 : Mim[chA][chB] *= gain;
1593 : }
1594 : }
1595 :
1596 : /* Store processing matrices */
1597 968875200 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
1598 : {
1599 1937750400 : for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
1600 : {
1601 1291833600 : hDiracDecBin->processMtxRePrev[chA][chB][bin] = hDiracDecBin->processMtxRe[chA][chB][bin];
1602 1291833600 : hDiracDecBin->processMtxImPrev[chA][chB][bin] = hDiracDecBin->processMtxIm[chA][chB][bin];
1603 1291833600 : hDiracDecBin->processMtxDecRePrev[chA][chB][bin] = hDiracDecBin->processMtxDecRe[chA][chB][bin];
1604 1291833600 : hDiracDecBin->processMtxDecImPrev[chA][chB][bin] = hDiracDecBin->processMtxDecIm[chA][chB][bin];
1605 :
1606 1291833600 : hDiracDecBin->processMtxRe[chA][chB][bin] = Mre[chA][chB];
1607 1291833600 : hDiracDecBin->processMtxIm[chA][chB][bin] = Mim[chA][chB];
1608 1291833600 : hDiracDecBin->processMtxDecRe[chA][chB][bin] = MdecRe[chA][chB];
1609 1291833600 : hDiracDecBin->processMtxDecIm[chA][chB][bin] = MdecIm[chA][chB];
1610 : }
1611 : }
1612 :
1613 322958400 : if ( separateCenterChannelRendering )
1614 : {
1615 : /* The rendering of the separate center channel in masa + mono mode.
1616 : * The center channel is processed with a gain factor 0.8414f to match the loudness of different processing paths */
1617 : float lRealp, lImagp, rRealp, rImagp;
1618 : float gainFactor;
1619 42198660 : int16_t aziDeg = 0;
1620 42198660 : int16_t eleDeg = 0;
1621 42198660 : uint8_t instantChange = 0;
1622 :
1623 42198660 : if ( ivas_format == MASA_ISM_FORMAT )
1624 : {
1625 41080860 : gainFactor = OMASA_TDREND_MATCHING_GAIN * sqrtf( hDiracDecBin->earlyPartEneCorrection[bin] );
1626 : }
1627 : else
1628 : {
1629 1117800 : gainFactor = 0.8414f * sqrtf( hDiracDecBin->earlyPartEneCorrection[bin] );
1630 : }
1631 :
1632 103231080 : for ( chB = 0; chB < nchanSeparateChannels; chB++ )
1633 : {
1634 61032420 : if ( ivas_format == MASA_ISM_FORMAT )
1635 : {
1636 59914620 : if ( ism_mode == ISM_MASA_MODE_DISC )
1637 : {
1638 33595680 : if ( hMasaIsmData->ism_dir_is_edited[chB] )
1639 : {
1640 0 : aziDeg = hMasaIsmData->azimuth_ism_edited[chB];
1641 0 : eleDeg = hMasaIsmData->elevation_ism_edited[chB];
1642 : }
1643 : else
1644 : {
1645 33595680 : aziDeg = hMasaIsmData->azimuth_ism[chB][dirac_read_idx];
1646 33595680 : eleDeg = hMasaIsmData->elevation_ism[chB][dirac_read_idx];
1647 : }
1648 : }
1649 : else
1650 : {
1651 26318940 : if ( ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ && hMasaIsmData->ism_dir_is_edited[hMasaIsmData->idx_separated_ism] )
1652 : {
1653 956160 : aziDeg = hMasaIsmData->azimuth_ism_edited[hMasaIsmData->idx_separated_ism];
1654 956160 : eleDeg = hMasaIsmData->elevation_ism_edited[hMasaIsmData->idx_separated_ism];
1655 : }
1656 : else
1657 : {
1658 25362780 : aziDeg = hMasaIsmData->azimuth_separated_ism[dirac_read_idx];
1659 25362780 : eleDeg = hMasaIsmData->elevation_separated_ism[dirac_read_idx];
1660 : }
1661 26318940 : instantChange = 1;
1662 : }
1663 : }
1664 :
1665 183097260 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
1666 : {
1667 122064840 : hDiracDecBin->processMtxRePrev[chA][chB + 2][bin] = hDiracDecBin->processMtxRe[chA][chB + 2][bin];
1668 122064840 : hDiracDecBin->processMtxImPrev[chA][chB + 2][bin] = hDiracDecBin->processMtxIm[chA][chB + 2][bin];
1669 : }
1670 :
1671 61032420 : getDirectPartGains( bin, aziDeg, eleDeg, &lRealp, &lImagp, &rRealp, &rImagp, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache[chB], isHeadtracked, *hDiracDecBin->phHrtfParambin );
1672 :
1673 61032420 : hDiracDecBin->processMtxRe[0][chB + 2][bin] = lRealp * gainFactor;
1674 61032420 : hDiracDecBin->processMtxIm[0][chB + 2][bin] = lImagp * gainFactor;
1675 61032420 : hDiracDecBin->processMtxRe[1][chB + 2][bin] = rRealp * gainFactor;
1676 61032420 : hDiracDecBin->processMtxIm[1][chB + 2][bin] = rImagp * gainFactor;
1677 :
1678 61032420 : if ( instantChange )
1679 : {
1680 78956820 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
1681 : {
1682 52637880 : hDiracDecBin->processMtxRePrev[chA][chB + 2][bin] = hDiracDecBin->processMtxRe[chA][chB + 2][bin];
1683 52637880 : hDiracDecBin->processMtxImPrev[chA][chB + 2][bin] = hDiracDecBin->processMtxIm[chA][chB + 2][bin];
1684 : }
1685 : }
1686 : }
1687 : }
1688 : }
1689 :
1690 6697981 : return;
1691 : }
1692 :
1693 :
1694 6697981 : static void ivas_dirac_dec_binaural_process_output(
1695 : DIRAC_DEC_BIN_HANDLE hDiracDecBin,
1696 : SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom,
1697 : HANDLE_CLDFB_FILTER_BANK cldfbSynDec[MAX_OUTPUT_CHANNELS],
1698 : float *output_f[],
1699 : float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
1700 : float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
1701 : const int16_t max_band_decorr,
1702 : const int16_t numInChannels,
1703 : const int16_t processReverb,
1704 : const int16_t subframe,
1705 : float outRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
1706 : float outIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
1707 : float reverbRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
1708 : float reverbIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
1709 : float decorrRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
1710 : float decorrIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
1711 : const uint8_t recompute )
1712 : {
1713 : int16_t slot, bin, chA, chB;
1714 : int16_t nBins;
1715 : float outSlotRe[CLDFB_NO_CHANNELS_MAX], outSlotIm[CLDFB_NO_CHANNELS_MAX];
1716 : float decSlotRe[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX], decSlotIm[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX];
1717 : float interpVal;
1718 : float *decSlotRePointer;
1719 : float *decSlotImPointer;
1720 : int16_t offsetSamples;
1721 : int16_t nSlots;
1722 :
1723 6697981 : nBins = hSpatParamRendCom->num_freq_bands;
1724 6697981 : offsetSamples = 0;
1725 6697981 : nSlots = hSpatParamRendCom->subframe_nbslots[subframe];
1726 :
1727 6697981 : if ( processReverb )
1728 : {
1729 : /* Process second / room effect part of binaural output when needed */
1730 2677834 : if ( recompute == 1 )
1731 : {
1732 2677834 : ivas_binaural_reverb_processSubframe( hDiracDecBin->hReverb, numInChannels, nSlots, inRe, inIm, reverbRe, reverbIm );
1733 : }
1734 : }
1735 :
1736 6697981 : interpVal = 0.0f;
1737 33361796 : for ( slot = 0; slot < nSlots; slot++ )
1738 : {
1739 26663815 : interpVal += 1.0f / (float) nSlots;
1740 26663815 : if ( !hDiracDecBin->useTdDecorr && max_band_decorr > 0 )
1741 : {
1742 18433542 : if ( recompute == 1 )
1743 : {
1744 13412110 : ivas_dirac_dec_decorrelate_slot( hDiracDecBin, nBins, slot, inRe, inIm, decSlotRe, decSlotIm );
1745 :
1746 40236330 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
1747 : {
1748 26824220 : mvr2r( decSlotRe[chA], decorrRe[chA][slot], CLDFB_NO_CHANNELS_MAX );
1749 26824220 : mvr2r( decSlotIm[chA], decorrIm[chA][slot], CLDFB_NO_CHANNELS_MAX );
1750 : }
1751 : }
1752 : else
1753 : {
1754 15064296 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
1755 : {
1756 10042864 : mvr2r( decorrRe[chA][slot], decSlotRe[chA], CLDFB_NO_CHANNELS_MAX );
1757 10042864 : mvr2r( decorrIm[chA][slot], decSlotIm[chA], CLDFB_NO_CHANNELS_MAX );
1758 : }
1759 : }
1760 : }
1761 :
1762 79991445 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
1763 : {
1764 : float *outSlotRePr, *outSlotImPr; /* Pointers needed for function call compatibility */
1765 :
1766 53327630 : set_zero( outSlotRe, CLDFB_NO_CHANNELS_MAX );
1767 53327630 : set_zero( outSlotIm, CLDFB_NO_CHANNELS_MAX );
1768 :
1769 : /* Processing of the first / HRTF part of the binaural output. */
1770 170526816 : for ( chB = 0; chB < numInChannels; chB++ )
1771 : {
1772 117199186 : if ( chB < BINAURAL_CHANNELS )
1773 : {
1774 : /* Decorrelator signal for TD decorrelation is stored in two input channels above the two normal inputs.
1775 : * It should be noted that TD decorrelation is used only in cases where numInChannels is 2. If this
1776 : * changes, additional adjustments are required. When using CLDFB decorrelator, we simply assign the
1777 : * pointers to buffers. */
1778 106655260 : if ( hDiracDecBin->useTdDecorr )
1779 : {
1780 29248664 : decSlotRePointer = inRe[chB + 2][slot];
1781 29248664 : decSlotImPointer = inIm[chB + 2][slot];
1782 : }
1783 : else
1784 : {
1785 77406596 : decSlotRePointer = decSlotRe[chB];
1786 77406596 : decSlotImPointer = decSlotIm[chB];
1787 : }
1788 : }
1789 : else
1790 : {
1791 10543926 : decSlotRePointer = NULL; /* below these pointers are used only for chB < 2 */
1792 10543926 : decSlotImPointer = NULL;
1793 : }
1794 :
1795 :
1796 5736018106 : for ( bin = 0; bin < nBins; bin++ )
1797 : {
1798 : float gain;
1799 :
1800 : /* Mixing using the formulated processing matrix M */
1801 5618818920 : gain = ( 1.0f - interpVal ) * hDiracDecBin->processMtxRePrev[chA][chB][bin] +
1802 5618818920 : interpVal * hDiracDecBin->processMtxRe[chA][chB][bin];
1803 5618818920 : outSlotRe[bin] += gain * inRe[chB][slot][bin];
1804 5618818920 : outSlotIm[bin] += gain * inIm[chB][slot][bin];
1805 :
1806 5618818920 : gain = ( 1.0f - interpVal ) * hDiracDecBin->processMtxImPrev[chA][chB][bin] +
1807 5618818920 : interpVal * hDiracDecBin->processMtxIm[chA][chB][bin];
1808 5618818920 : outSlotRe[bin] -= gain * inIm[chB][slot][bin];
1809 5618818920 : outSlotIm[bin] += gain * inRe[chB][slot][bin];
1810 :
1811 : /* Mixing decorrelated signals using the formulated residual processing matrix Mdec */
1812 5618818920 : if ( bin < max_band_decorr && chB < 2 )
1813 : {
1814 2428922040 : gain = ( 1.0f - interpVal ) * hDiracDecBin->processMtxDecRePrev[chA][chB][bin] +
1815 2428922040 : interpVal * hDiracDecBin->processMtxDecRe[chA][chB][bin];
1816 2428922040 : outSlotRe[bin] += gain * decSlotRePointer[bin];
1817 2428922040 : outSlotIm[bin] += gain * decSlotImPointer[bin];
1818 :
1819 2428922040 : gain = ( 1.0f - interpVal ) * hDiracDecBin->processMtxDecImPrev[chA][chB][bin] +
1820 2428922040 : interpVal * hDiracDecBin->processMtxDecIm[chA][chB][bin];
1821 2428922040 : outSlotRe[bin] -= gain * decSlotImPointer[bin];
1822 2428922040 : outSlotIm[bin] += gain * decSlotRePointer[bin];
1823 : }
1824 : }
1825 : }
1826 :
1827 53327630 : if ( processReverb )
1828 : {
1829 : /* Combine second (reverb) part with the first (HRTF) part to obtain binaural output signal with room effect */
1830 21409538 : v_add( outSlotRe, reverbRe[chA][slot], outSlotRe, CLDFB_NO_CHANNELS_MAX );
1831 21409538 : v_add( outSlotIm, reverbIm[chA][slot], outSlotIm, CLDFB_NO_CHANNELS_MAX );
1832 : }
1833 :
1834 53327630 : outSlotRePr = &( outSlotRe[0] );
1835 53327630 : outSlotImPr = &( outSlotIm[0] );
1836 :
1837 53327630 : if ( outRe != NULL && outIm != NULL )
1838 : {
1839 : /* provide the data outside in CLDFB domain => mainly for split rendering */
1840 16121744 : mvr2r( outSlotRePr, outRe[chA][slot], CLDFB_NO_CHANNELS_MAX );
1841 16121744 : mvr2r( outSlotImPr, outIm[chA][slot], CLDFB_NO_CHANNELS_MAX );
1842 : }
1843 53327630 : if ( recompute == 1 )
1844 : {
1845 : /* Inverse filter bank */
1846 41167118 : cldfbSynthesis( &outSlotRePr, &outSlotImPr, &( output_f[chA][nBins * slot + offsetSamples] ), nBins, cldfbSynDec[chA] );
1847 : }
1848 : }
1849 : }
1850 :
1851 6697981 : return;
1852 : }
1853 :
1854 :
1855 721538 : static void adaptTransportSignalsHeadtracked(
1856 : COMBINED_ORIENTATION_HANDLE hHeadTrackData,
1857 : float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
1858 : float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
1859 : const int16_t nBins,
1860 : const int16_t nSlots,
1861 : float Rmat[3][3] )
1862 : {
1863 : int16_t slot, ch, bin, louderCh;
1864 : float ILD, mono_factor_ILD, mono_factor_rotation, mono_factor, y_val, ene_proc, ene_target;
1865 : int16_t max_band;
1866 : float eqVal;
1867 : int16_t band_idx, bin_lo, bin_hi;
1868 :
1869 : /* Determine head-orientation-based mono factor.
1870 : Rmat[1][1] entry informs how close the ears are aligned according to transport signals. */
1871 721538 : y_val = 1.0f - fabsf( Rmat[1][1] );
1872 721538 : mono_factor_rotation = ( y_val - ADAPT_HTPROTO_ROT_LIM_0 ) / ( ADAPT_HTPROTO_ROT_LIM_1 - ADAPT_HTPROTO_ROT_LIM_0 );
1873 721538 : mono_factor_rotation = fmaxf( 0.0f, fminf( 1.0f, mono_factor_rotation ) );
1874 :
1875 : /* Adapt transport signals in frequency bands */
1876 : /* 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 */
1877 :
1878 721538 : max_band = 0;
1879 17712500 : while ( max_band < MASA_FREQUENCY_BANDS && MASA_band_grouping_24[max_band] < nBins )
1880 : {
1881 16990962 : max_band++;
1882 : }
1883 :
1884 17712500 : for ( band_idx = 0; band_idx < max_band; band_idx++ )
1885 : {
1886 : float ch_nrg[2]; /* storage for input signal channel energies */
1887 16990962 : bin_lo = MASA_band_grouping_24[band_idx];
1888 16990962 : bin_hi = min( MASA_band_grouping_24[band_idx + 1], (int16_t) nBins );
1889 50972886 : for ( ch = 0; ch < 2; ch++ )
1890 : {
1891 33981924 : ch_nrg[ch] = 0.0f;
1892 169210500 : for ( slot = 0; slot < nSlots; slot++ )
1893 : {
1894 438083016 : for ( bin = bin_lo; bin < bin_hi; bin++ )
1895 : {
1896 302854440 : ch_nrg[ch] += ( inRe[ch][slot][bin] * inRe[ch][slot][bin] ) + ( inIm[ch][slot][bin] * inIm[ch][slot][bin] );
1897 : }
1898 : }
1899 33981924 : hHeadTrackData->chEneIIR[ch][band_idx] *= ADAPT_HTPROTO_IIR_FAC;
1900 33981924 : hHeadTrackData->chEneIIR[ch][band_idx] += ( 1.0f - ADAPT_HTPROTO_IIR_FAC ) * ch_nrg[ch];
1901 : }
1902 :
1903 : /* Determine ILD */
1904 16990962 : ILD = fabsf( 10.0f * log10f( fmaxf( 1e-12f, hHeadTrackData->chEneIIR[0][band_idx] ) / fmaxf( 1e-12f, hHeadTrackData->chEneIIR[1][band_idx] ) ) );
1905 16990962 : if ( hHeadTrackData->chEneIIR[1][band_idx] > hHeadTrackData->chEneIIR[0][band_idx] )
1906 : {
1907 8482112 : louderCh = 1;
1908 : }
1909 : else
1910 : {
1911 8508850 : louderCh = 0;
1912 : }
1913 :
1914 : /* Determine ILD-based mono factor */
1915 16990962 : mono_factor_ILD = ( ILD - ADAPT_HTPROTO_ILD_LIM_DB0 ) / ( ADAPT_HTPROTO_ILD_LIM_DB1 - ADAPT_HTPROTO_ILD_LIM_DB0 );
1916 16990962 : mono_factor_ILD = fmaxf( 0.0f, fminf( 1.0f, mono_factor_ILD ) );
1917 :
1918 : /* Combine mono factors */
1919 16990962 : mono_factor = mono_factor_ILD * mono_factor_rotation;
1920 :
1921 : /* Mix original audio and sum signal according to determined mono factor */
1922 50972886 : for ( ch = 0; ch < 2; ch++ )
1923 : {
1924 33981924 : if ( ch != louderCh )
1925 : {
1926 16990962 : float band_nrg = 0.0f;
1927 :
1928 84605250 : for ( slot = 0; slot < nSlots; slot++ )
1929 : {
1930 219041508 : for ( bin = bin_lo; bin < bin_hi; bin++ )
1931 : {
1932 : /* mono sum signal with the computed weight + rest from the original channel */
1933 151427220 : inRe[ch][slot][bin] = mono_factor * ( inRe[0][slot][bin] + inRe[1][slot][bin] ) + ( 1.0f - mono_factor ) * inRe[ch][slot][bin];
1934 151427220 : inIm[ch][slot][bin] = mono_factor * ( inIm[0][slot][bin] + inIm[1][slot][bin] ) + ( 1.0f - mono_factor ) * inIm[ch][slot][bin];
1935 151427220 : band_nrg += ( inRe[ch][slot][bin] * inRe[ch][slot][bin] ) + ( inIm[ch][slot][bin] * inIm[ch][slot][bin] );
1936 : }
1937 : }
1938 16990962 : hHeadTrackData->procChEneIIR[ch][band_idx] *= ADAPT_HTPROTO_IIR_FAC;
1939 16990962 : hHeadTrackData->procChEneIIR[ch][band_idx] += ( 1.0f - ADAPT_HTPROTO_IIR_FAC ) * band_nrg;
1940 : }
1941 : else
1942 : {
1943 : /* processed signal is input. use the original channel, so no need to compute new signals or signal energy */
1944 16990962 : hHeadTrackData->procChEneIIR[ch][band_idx] *= ADAPT_HTPROTO_IIR_FAC;
1945 16990962 : hHeadTrackData->procChEneIIR[ch][band_idx] += ( 1.0f - ADAPT_HTPROTO_IIR_FAC ) * ch_nrg[ch];
1946 : }
1947 : }
1948 :
1949 : /* Equalize */
1950 16990962 : ene_target = hHeadTrackData->chEneIIR[0][band_idx] + hHeadTrackData->chEneIIR[1][band_idx];
1951 16990962 : ene_proc = hHeadTrackData->procChEneIIR[0][band_idx] + hHeadTrackData->procChEneIIR[1][band_idx];
1952 16990962 : eqVal = fminf( 4.0f, sqrtf( ene_target / fmaxf( 1e-12f, ene_proc ) ) );
1953 :
1954 84605250 : for ( slot = 0; slot < nSlots; slot++ )
1955 : {
1956 202842864 : for ( ch = 0; ch < 2; ch++ )
1957 : {
1958 438083016 : for ( bin = bin_lo; bin < bin_hi; bin++ )
1959 : {
1960 302854440 : inRe[ch][slot][bin] *= eqVal;
1961 302854440 : inIm[ch][slot][bin] *= eqVal;
1962 : }
1963 : }
1964 : }
1965 : }
1966 :
1967 721538 : return;
1968 : }
1969 :
1970 721538 : static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked(
1971 : COMBINED_ORIENTATION_HANDLE hHeadTrackData,
1972 : float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
1973 : float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
1974 : const int16_t nBins,
1975 : const int16_t nSlots,
1976 : float Rmat[3][3] )
1977 : {
1978 : int16_t slot, bin, ch;
1979 : float tmpVal;
1980 :
1981 : /* When not currently in prototype signal left-right switching procedure, check if such switching is needed */
1982 721538 : if ( hHeadTrackData->lrSwitchedNext == hHeadTrackData->lrSwitchedCurrent )
1983 : {
1984 506077 : float thresholdDotProduct = 0.17f; /* Corresponds to 10-degree switching threshold */
1985 506077 : if ( ( hHeadTrackData->lrSwitchedCurrent == 0 ) && ( Rmat[1][1] < -thresholdDotProduct ) )
1986 : {
1987 1386 : hHeadTrackData->lrSwitchedNext = 1;
1988 : }
1989 506077 : if ( ( hHeadTrackData->lrSwitchedCurrent == 1 ) && ( Rmat[1][1] > thresholdDotProduct ) )
1990 : {
1991 948 : hHeadTrackData->lrSwitchedNext = 0;
1992 : }
1993 : }
1994 :
1995 : /* When currently in interpolation */
1996 721538 : if ( hHeadTrackData->lrSwitchedNext != hHeadTrackData->lrSwitchedCurrent )
1997 : {
1998 1079864 : for ( slot = 0; slot < nSlots; slot++ )
1999 : {
2000 : float switchOrderFactor, origOrderFactor;
2001 :
2002 862069 : hHeadTrackData->lrSwitchInterpVal += 0.0025f; /* Corresponds to 0.5 seconds interpolation time */
2003 :
2004 862069 : if ( hHeadTrackData->lrSwitchInterpVal > 0.999f )
2005 : {
2006 : /* Stop interpolation, reset values */
2007 1985 : hHeadTrackData->lrSwitchInterpVal = 0.0f;
2008 1985 : hHeadTrackData->lrSwitchedCurrent = hHeadTrackData->lrSwitchedNext;
2009 : }
2010 :
2011 : /* Gains for determining portion of switched channel order and original channel order */
2012 862069 : tmpVal = (float) hHeadTrackData->lrSwitchedNext * hHeadTrackData->lrSwitchInterpVal;
2013 862069 : tmpVal += (float) hHeadTrackData->lrSwitchedCurrent * ( 1.0f - hHeadTrackData->lrSwitchInterpVal );
2014 862069 : switchOrderFactor = sqrtf( tmpVal );
2015 862069 : origOrderFactor = sqrtf( 1.0f - tmpVal );
2016 :
2017 51078769 : for ( bin = 0; bin < nBins; bin++ )
2018 : {
2019 : /* determine original order (1) signals and switched order (2) signals */
2020 : float re1[BINAURAL_CHANNELS], re2[BINAURAL_CHANNELS], im1[BINAURAL_CHANNELS], im2[BINAURAL_CHANNELS];
2021 :
2022 150650100 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
2023 : {
2024 100433400 : re1[ch] = inRe[ch][slot][bin] * origOrderFactor;
2025 100433400 : re2[ch] = inRe[1 - ch][slot][bin] * switchOrderFactor;
2026 100433400 : im1[ch] = inIm[ch][slot][bin] * origOrderFactor;
2027 100433400 : im2[ch] = inIm[1 - ch][slot][bin] * switchOrderFactor;
2028 : }
2029 :
2030 150650100 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
2031 : {
2032 : float eneRef, ene, eq;
2033 :
2034 : /* Interpolate / mix original and switched order signals */
2035 100433400 : inRe[ch][slot][bin] = re1[ch] + re2[ch];
2036 100433400 : inIm[ch][slot][bin] = im1[ch] + im2[ch];
2037 :
2038 : /* Equalize interpolated signals to preserve energy per bin */
2039 100433400 : eneRef = ( re1[ch] * re1[ch] ) + ( re2[ch] * re2[ch] ) + ( im1[ch] * im1[ch] ) + ( im2[ch] * im2[ch] );
2040 100433400 : ene = ( inRe[ch][slot][bin] * inRe[ch][slot][bin] ) + ( inIm[ch][slot][bin] * inIm[ch][slot][bin] );
2041 100433400 : eq = sqrtf( eneRef / fmaxf( 1e-12f, ene ) );
2042 100433400 : eq = fminf( 4.0f, eq );
2043 100433400 : inRe[ch][slot][bin] *= eq;
2044 100433400 : inIm[ch][slot][bin] *= eq;
2045 : }
2046 : }
2047 : }
2048 : }
2049 : else
2050 : {
2051 : /* If not in interpolation, but in switched prototype situation, then switch left and right channels */
2052 503743 : if ( hHeadTrackData->lrSwitchedCurrent == 1 )
2053 : {
2054 573314 : for ( slot = 0; slot < nSlots; slot++ )
2055 : {
2056 25626785 : for ( bin = 0; bin < nBins; bin++ )
2057 : {
2058 25169100 : tmpVal = inRe[0][slot][bin];
2059 25169100 : inRe[0][slot][bin] = inRe[1][slot][bin];
2060 25169100 : inRe[1][slot][bin] = tmpVal;
2061 25169100 : tmpVal = inIm[0][slot][bin];
2062 25169100 : inIm[0][slot][bin] = inIm[1][slot][bin];
2063 25169100 : inIm[1][slot][bin] = tmpVal;
2064 : }
2065 : }
2066 : }
2067 : }
2068 :
2069 721538 : return;
2070 : }
2071 :
2072 :
2073 951334140 : static void eig2x2(
2074 : const float E1,
2075 : const float E2,
2076 : const float Cre,
2077 : const float Cim,
2078 : float Ure[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2079 : float Uim[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2080 : float D[BINAURAL_CHANNELS] )
2081 : {
2082 : int16_t chA, chB, ch;
2083 : float s, normVal, crossSquare, a, pm, add;
2084 :
2085 2854002420 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
2086 : {
2087 5708004840 : for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
2088 : {
2089 3805336560 : Ure[chA][chB] = 0.0f;
2090 3805336560 : Uim[chA][chB] = 0.0f;
2091 : }
2092 : }
2093 :
2094 951334140 : crossSquare = ( Cre * Cre ) + ( Cim * Cim );
2095 951334140 : a = ( E1 + E2 ) * ( E1 + E2 ) - 4.0f * ( ( E1 * E2 ) - crossSquare );
2096 951334140 : pm = 0.5f * sqrtf( max( 0.0f, a ) );
2097 951334140 : add = 0.5f * ( E1 + E2 );
2098 :
2099 951334140 : D[0] = add + pm;
2100 951334140 : D[1] = max( 0.0f, add - pm );
2101 :
2102 : /* Numeric case, when input is practically zeros */
2103 951334140 : if ( D[0] < 1e-12f )
2104 : {
2105 18626487 : Ure[0][0] = 1.0f;
2106 18626487 : Ure[1][1] = 1.0f;
2107 :
2108 18626487 : return;
2109 : }
2110 :
2111 : /* Numeric case, when input is near an identity matrix with a gain */
2112 932707653 : if ( pm < ( 1e-3f * add ) )
2113 : {
2114 92305066 : Ure[0][0] = 1.0f;
2115 92305066 : Ure[1][1] = 1.0f;
2116 :
2117 92305066 : return;
2118 : }
2119 :
2120 : /* Eigenvectors */
2121 2521207761 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
2122 : {
2123 1680805174 : if ( fabsf( E2 - D[ch] ) > fabsf( E1 - D[ch] ) )
2124 : {
2125 717927186 : s = D[ch] - E2;
2126 717927186 : normVal = sqrtf( 1.0f / ( 1e-12f + crossSquare + s * s ) );
2127 :
2128 717927186 : Ure[0][ch] = s * normVal;
2129 717927186 : Ure[1][ch] = Cre * normVal;
2130 717927186 : Uim[1][ch] = Cim * normVal;
2131 : }
2132 : else
2133 : {
2134 962877988 : s = D[ch] - E1;
2135 962877988 : normVal = sqrtf( 1.0f / ( 1e-12f + crossSquare + s * s ) );
2136 :
2137 962877988 : Ure[1][ch] = s * normVal;
2138 962877988 : Ure[0][ch] = Cre * normVal;
2139 962877988 : Uim[0][ch] = -Cim * normVal;
2140 : }
2141 : }
2142 :
2143 840402587 : return;
2144 : }
2145 :
2146 :
2147 475667070 : static void matrixDiagMul(
2148 : float reIn[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2149 : float imIn[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2150 : const float D[BINAURAL_CHANNELS],
2151 : float reOut[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2152 : float imOut[BINAURAL_CHANNELS][BINAURAL_CHANNELS] )
2153 : {
2154 : int16_t chA, chB;
2155 :
2156 1427001210 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
2157 : {
2158 2854002420 : for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
2159 : {
2160 1902668280 : reOut[chA][chB] = reIn[chA][chB] * D[chB];
2161 1902668280 : imOut[chA][chB] = imIn[chA][chB] * D[chB];
2162 : }
2163 : }
2164 :
2165 475667070 : return;
2166 : }
2167 :
2168 :
2169 1749959610 : static void matrixMul(
2170 : float Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2171 : float Aim[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2172 : float Bre[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2173 : float Bim[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2174 : float outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2175 : float outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS] )
2176 : {
2177 : int16_t chA, chB;
2178 :
2179 5249878830 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
2180 : {
2181 10499757660 : for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
2182 : {
2183 6999838440 : outRe[chA][chB] = Are[chA][0] * Bre[0][chB] + Are[chA][1] * Bre[1][chB];
2184 6999838440 : outRe[chA][chB] -= Aim[chA][0] * Bim[0][chB] + Aim[chA][1] * Bim[1][chB];
2185 6999838440 : outIm[chA][chB] = Aim[chA][0] * Bre[0][chB] + Aim[chA][1] * Bre[1][chB];
2186 6999838440 : outIm[chA][chB] += Are[chA][0] * Bim[0][chB] + Are[chA][1] * Bim[1][chB];
2187 : }
2188 : }
2189 :
2190 1749959610 : return;
2191 : }
2192 :
2193 :
2194 475667070 : static void matrixTransp1Mul(
2195 : float Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2196 : float Aim[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2197 : float Bre[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2198 : float Bim[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2199 : float outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2200 : float outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS] )
2201 : {
2202 : int16_t chA, chB;
2203 :
2204 1427001210 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
2205 : {
2206 2854002420 : for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
2207 : {
2208 1902668280 : outRe[chA][chB] = Are[0][chA] * Bre[0][chB] + Are[1][chA] * Bre[1][chB];
2209 1902668280 : outRe[chA][chB] -= -Aim[0][chA] * Bim[0][chB] - Aim[1][chA] * Bim[1][chB];
2210 1902668280 : outIm[chA][chB] = -Aim[0][chA] * Bre[0][chB] - Aim[1][chA] * Bre[1][chB];
2211 1902668280 : outIm[chA][chB] += Are[0][chA] * Bim[0][chB] + Are[1][chA] * Bim[1][chB];
2212 : }
2213 : }
2214 :
2215 475667070 : return;
2216 : }
2217 :
2218 :
2219 1274292540 : static void matrixTransp2Mul(
2220 : float Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2221 : float Aim[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2222 : float Bre[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2223 : float Bim[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2224 : float outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2225 : float outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS] )
2226 : {
2227 : int16_t chA, chB;
2228 :
2229 3822877620 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
2230 : {
2231 7645755240 : for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
2232 : {
2233 5097170160 : outRe[chA][chB] = Are[chA][0] * Bre[chB][0] + Are[chA][1] * Bre[chB][1];
2234 5097170160 : outRe[chA][chB] -= Aim[chA][0] * ( -Bim[chB][0] ) + Aim[chA][1] * ( -Bim[chB][1] );
2235 5097170160 : outIm[chA][chB] = Aim[chA][0] * Bre[chB][0] + Aim[chA][1] * Bre[chB][1];
2236 5097170160 : outIm[chA][chB] += Are[chA][0] * ( -Bim[chB][0] ) + Are[chA][1] * ( -Bim[chB][1] );
2237 : }
2238 : }
2239 :
2240 1274292540 : return;
2241 : }
2242 :
2243 :
2244 475667070 : static void chol2x2(
2245 : const float E1,
2246 : const float E2,
2247 : const float Cre,
2248 : const float Cim,
2249 : float outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2250 : float outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS] )
2251 : {
2252 : int16_t chA, chB;
2253 : float sqrtVal;
2254 :
2255 1427001210 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
2256 : {
2257 2854002420 : for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
2258 : {
2259 1902668280 : outRe[chA][chB] = 0.0f;
2260 1902668280 : outIm[chA][chB] = 0.0f;
2261 : }
2262 : }
2263 :
2264 475667070 : if ( E1 > E2 ) /* Perform Cholesky decomposition according to louder channel first */
2265 : {
2266 226974688 : outRe[0][0] = sqrtf( E1 );
2267 226974688 : outRe[1][0] = Cre / ( 1e-12f + outRe[0][0] );
2268 226974688 : outIm[1][0] = Cim / ( 1e-12f + outRe[0][0] );
2269 226974688 : sqrtVal = E2 - ( Cre * Cre + Cim * Cim ) / ( 1e-12f + E1 );
2270 226974688 : outRe[1][1] = sqrtf( max( 0.0f, sqrtVal ) );
2271 : }
2272 : else
2273 : {
2274 248692382 : outRe[1][1] = sqrtf( E2 );
2275 248692382 : outRe[0][1] = Cre / ( 1e-12f + outRe[1][1] );
2276 248692382 : outIm[0][1] = -Cim / ( 1e-12f + outRe[1][1] );
2277 248692382 : sqrtVal = E1 - ( Cre * Cre + Cim * Cim ) / ( 1e-12f + E2 );
2278 248692382 : outRe[0][0] = sqrtf( max( 0.0f, sqrtVal ) );
2279 : }
2280 :
2281 475667070 : return;
2282 : }
2283 :
2284 :
2285 475667070 : static void formulate2x2MixingMatrix(
2286 : float Ein1,
2287 : float Ein2,
2288 : float CinRe,
2289 : float CinIm,
2290 : float Eout1,
2291 : float Eout2,
2292 : float CoutRe,
2293 : float CoutIm,
2294 : float Q[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2295 : float Mre[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2296 : float Mim[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
2297 : const float regularizationFactor )
2298 : {
2299 : /*
2300 : This function implements a 2x2 solution for an optimized spatial audio rendering algorithm
2301 : Vilkamo, J., Bäckström, T. and Kuntz, A., 2013.
2302 : "Optimized covariance domain framework for time–frequency processing of spatial audio."
2303 : Journal of the Audio Engineering Society, 61(6), pp.403-411.
2304 :
2305 : The result of the formulas below are the same as those in the publication, however, some
2306 : derivation details differ for as simple as possible 2x2 formulattion
2307 : */
2308 : int16_t chA, chB;
2309 : float maxEne, maxEneDiv;
2310 : float KyRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], KyIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
2311 : float Uxre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Uxim[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
2312 : float Sx[BINAURAL_CHANNELS], Kxre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Kxim[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
2313 : float tmpRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], tmpIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
2314 : float Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Aim[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
2315 : float Ure[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Uim[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
2316 : float D[BINAURAL_CHANNELS];
2317 : float div[BINAURAL_CHANNELS];
2318 : float Ghat[BINAURAL_CHANNELS];
2319 : float GhatQ[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
2320 : float Pre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Pim[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
2321 :
2322 : /* Normalize energy values */
2323 475667070 : maxEne = Ein1;
2324 475667070 : maxEne = max( maxEne, Ein2 );
2325 475667070 : maxEne = max( maxEne, Eout1 );
2326 475667070 : maxEne = max( maxEne, Eout2 );
2327 475667070 : maxEneDiv = 1.0f / ( maxEne + 1e-12f );
2328 475667070 : Ein1 *= maxEneDiv;
2329 475667070 : Ein2 *= maxEneDiv;
2330 475667070 : CinRe *= maxEneDiv;
2331 475667070 : CinIm *= maxEneDiv;
2332 475667070 : Eout1 *= maxEneDiv;
2333 475667070 : Eout2 *= maxEneDiv;
2334 475667070 : CoutRe *= maxEneDiv;
2335 475667070 : CoutIm *= maxEneDiv;
2336 :
2337 : /* Cholesky decomposition of target / output covariance matrix */
2338 475667070 : chol2x2( Eout1, Eout2, CoutRe, CoutIm, KyRe, KyIm );
2339 :
2340 : /* Eigendecomposition of input covariance matrix */
2341 475667070 : eig2x2( Ein1, Ein2, CinRe, CinIm, Uxre, Uxim, Sx );
2342 :
2343 : /* Eigendecomposition to Kx -- Ux Sx Ux' -> Kx Kx'*/
2344 475667070 : Sx[0] = sqrtf( Sx[0] );
2345 475667070 : Sx[1] = sqrtf( Sx[1] );
2346 475667070 : matrixDiagMul( Uxre, Uxim, Sx, Kxre, Kxim );
2347 :
2348 : /* Regularize the diagonal Sx for matrix inversion */
2349 475667070 : Sx[0] = max( Sx[0], regularizationFactor * Sx[1] );
2350 475667070 : Sx[1] = max( Sx[1], regularizationFactor * Sx[0] );
2351 :
2352 : /* This is equivalent to the prototype signal energy normalization in the publication */
2353 475667070 : Ghat[0] = sqrtf( Eout1 / ( 1e-12f + max( Ein1, 0.001f * Ein2 ) ) );
2354 475667070 : Ghat[1] = sqrtf( Eout2 / ( 1e-12f + max( Ein2, 0.001f * Ein1 ) ) );
2355 :
2356 : /* Matrix multiplication, tmp = Ky' * G_hat * Q */
2357 1427001210 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
2358 : {
2359 951334140 : GhatQ[chA][0] = Q[chA][0] * Ghat[chA];
2360 951334140 : GhatQ[chA][1] = Q[chA][1] * Ghat[chA];
2361 : }
2362 1427001210 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
2363 : {
2364 2854002420 : for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
2365 : {
2366 1902668280 : tmpRe[chA][chB] = KyRe[0][chA] * GhatQ[0][chB] + KyRe[1][chA] * GhatQ[1][chB];
2367 1902668280 : tmpIm[chA][chB] = -KyIm[0][chA] * GhatQ[0][chB] - KyIm[1][chA] * GhatQ[1][chB];
2368 : }
2369 : }
2370 :
2371 : /* A = Ky' * G_hat * Q * Kx (see publication) */
2372 475667070 : matrixMul( tmpRe, tmpIm, Kxre, Kxim, Are, Aim );
2373 :
2374 : /* Find nearest orthonormal matrix P to A = Ky' * G_hat * Q * Kx
2375 : For matrix A that is P = A(A'A)^0.5
2376 : */
2377 475667070 : matrixTransp1Mul( Are, Aim, Are, Aim, tmpRe, tmpIm );
2378 :
2379 475667070 : eig2x2( tmpRe[0][0], tmpRe[1][1], tmpRe[1][0], tmpIm[1][0], Ure, Uim, D );
2380 :
2381 475667070 : div[0] = min( 10000.0f, sqrtf( 1.0f / ( 1e-12f + D[0] ) ) );
2382 475667070 : div[1] = min( 10000.0f, sqrtf( 1.0f / ( 1e-12f + D[1] ) ) );
2383 :
2384 475667070 : matrixMul( Are, Aim, Ure, Uim, tmpRe, tmpIm );
2385 :
2386 1427001210 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
2387 : {
2388 2854002420 : for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
2389 : {
2390 1902668280 : tmpRe[chA][chB] *= div[chB];
2391 1902668280 : tmpIm[chA][chB] *= div[chB];
2392 : }
2393 : }
2394 :
2395 475667070 : matrixTransp2Mul( tmpRe, tmpIm, Ure, Uim, Pre, Pim ); /* Nearest orthonormal matrix P to matrix A formulated */
2396 :
2397 : /* These are the final formulas of the JAES publication M = Ky P Kx^(-1) */
2398 1427001210 : for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
2399 : {
2400 2854002420 : for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
2401 : {
2402 1902668280 : Pre[chA][chB] /= Sx[chB] + 1e-12f;
2403 1902668280 : Pim[chA][chB] /= Sx[chB] + 1e-12f;
2404 : }
2405 : }
2406 :
2407 475667070 : matrixMul( KyRe, KyIm, Pre, Pim, tmpRe, tmpIm );
2408 :
2409 475667070 : matrixTransp2Mul( tmpRe, tmpIm, Uxre, Uxim, Mre, Mim );
2410 :
2411 475667070 : return;
2412 : }
2413 :
2414 :
2415 681221974 : static void getDirectPartGains(
2416 : const int16_t bin,
2417 : int16_t aziDeg,
2418 : int16_t eleDeg,
2419 : float *lRealp,
2420 : float *lImagp,
2421 : float *rRealp,
2422 : float *rImagp,
2423 : const uint8_t renderStereoOutputInsteadOfBinaural,
2424 : float Rmat[3][3],
2425 : PARAMBIN_HRTF_GAIN_CACHE *gainCache,
2426 : const int16_t isHeadtracked,
2427 : HRTFS_PARAMBIN_HANDLE hHrtfParambin )
2428 : {
2429 : float aziRad, eleRad;
2430 : float y, mappedX, aziRadMapped, A, A2, A3;
2431 :
2432 681221974 : if ( renderStereoOutputInsteadOfBinaural ) /* In stereo (i.e. non-binaural) rendering mode */
2433 : {
2434 35408477 : *lImagp = 0.0f;
2435 35408477 : *rImagp = 0.0f;
2436 35408477 : if ( aziDeg == gainCache->azi && eleDeg == gainCache->ele )
2437 : {
2438 30607348 : *lRealp = gainCache->shVec[0]; /* Reused memory */
2439 30607348 : *rRealp = gainCache->shVec[1]; /* Reused memory */
2440 : }
2441 : else
2442 : {
2443 : /* Convert azi and ele to an azi value of the cone of confusion */
2444 4801129 : aziRad = (float) aziDeg * PI_OVER_180;
2445 4801129 : eleRad = (float) eleDeg * PI_OVER_180;
2446 4801129 : y = ( sinf( aziRad ) * cosf( eleRad ) );
2447 4801129 : mappedX = sqrtf( max( 0.0f, 1.0f - ( y * y ) ) );
2448 4801129 : aziRadMapped = atan2f( y, mappedX );
2449 :
2450 : /* Determine the real valued amplitude panning gains */
2451 4801129 : if ( aziRadMapped >= LS_ANGLE_RAD_30_DEG )
2452 : { /* Left side */
2453 1125088 : *lRealp = 1.0f;
2454 1125088 : *rRealp = 0.0f;
2455 : }
2456 3676041 : else if ( aziRadMapped <= -LS_ANGLE_RAD_30_DEG )
2457 : { /* Right side */
2458 2421610 : *lRealp = 0.0f;
2459 2421610 : *rRealp = 1.0f;
2460 : }
2461 : else /* Tangent panning law */
2462 : {
2463 1254431 : A = tanf( aziRadMapped ) * INV_TAN_LS_ANGLE_RAD_30_DEG;
2464 1254431 : A2 = ( A - 1.0f ) / max( 0.001f, A + 1.0f );
2465 1254431 : A3 = 1.0f / ( A2 * A2 + 1.0f );
2466 1254431 : *lRealp = sqrtf( A3 );
2467 1254431 : *rRealp = sqrtf( 1.0f - A3 );
2468 : }
2469 : /* Scaling to have the same expected gain as for the HRTF rendering */
2470 4801129 : *lRealp *= SQRT2;
2471 4801129 : *rRealp *= SQRT2;
2472 :
2473 : /* Store to gain cache */
2474 4801129 : gainCache->azi = aziDeg;
2475 4801129 : gainCache->ele = eleDeg;
2476 4801129 : gainCache->shVec[0] = *lRealp; /* Reuse memory */
2477 4801129 : gainCache->shVec[1] = *rRealp; /* Reuse memory */
2478 : }
2479 : }
2480 : else /* In regular binaural rendering mode */
2481 : {
2482 645813497 : if ( aziDeg == gainCache->azi && eleDeg == gainCache->ele )
2483 : {
2484 445790462 : hrtfShGetHrtf( bin, aziDeg, eleDeg, lRealp, lImagp, rRealp, rImagp, gainCache, TRUE, hHrtfParambin );
2485 : }
2486 : else
2487 : {
2488 200023035 : gainCache->azi = aziDeg;
2489 200023035 : gainCache->ele = eleDeg;
2490 200023035 : if ( isHeadtracked )
2491 : {
2492 89571075 : rotateAziEle( (float) aziDeg, (float) eleDeg, &aziDeg, &eleDeg, Rmat, 0 );
2493 : }
2494 200023035 : hrtfShGetHrtf( bin, aziDeg, eleDeg, lRealp, lImagp, rRealp, rImagp, gainCache, FALSE, hHrtfParambin );
2495 : }
2496 : }
2497 :
2498 681221974 : return;
2499 : }
2500 :
2501 :
2502 645813497 : static void hrtfShGetHrtf(
2503 : const int16_t bin,
2504 : const int16_t aziDeg,
2505 : const int16_t eleDeg,
2506 : float *lRealp,
2507 : float *lImagp,
2508 : float *rRealp,
2509 : float *rImagp,
2510 : PARAMBIN_HRTF_GAIN_CACHE *gainCache,
2511 : const int16_t useCachedValue,
2512 : HRTFS_PARAMBIN_HANDLE hHrtfParambin )
2513 : {
2514 : int16_t k;
2515 : float( *hrtfShCoeffsReInt )[16][60];
2516 : float( *hrtfShCoeffsImInt )[16][60];
2517 645813497 : hrtfShCoeffsReInt = hHrtfParambin->hrtfShCoeffsRe;
2518 645813497 : hrtfShCoeffsImInt = hHrtfParambin->hrtfShCoeffsIm;
2519 :
2520 645813497 : *lRealp = 0.0f;
2521 645813497 : *lImagp = 0.0f;
2522 645813497 : *rRealp = 0.0f;
2523 645813497 : *rImagp = 0.0f;
2524 :
2525 645813497 : if ( useCachedValue )
2526 : {
2527 : float *shVec;
2528 445790462 : shVec = gainCache->shVec;
2529 :
2530 7578437854 : for ( k = 0; k < HRTF_SH_CHANNELS; k++ )
2531 : {
2532 7132647392 : *lRealp += hrtfShCoeffsReInt[0][k][bin] * shVec[k];
2533 7132647392 : *lImagp += hrtfShCoeffsImInt[0][k][bin] * shVec[k];
2534 7132647392 : *rRealp += hrtfShCoeffsReInt[1][k][bin] * shVec[k];
2535 7132647392 : *rImagp += hrtfShCoeffsImInt[1][k][bin] * shVec[k];
2536 : }
2537 : }
2538 : else
2539 : {
2540 : float shVec[HRTF_SH_CHANNELS];
2541 :
2542 200023035 : ivas_dirac_dec_get_response( aziDeg,
2543 : eleDeg,
2544 : shVec,
2545 : HRTF_SH_ORDER );
2546 :
2547 3400391595 : for ( k = 0; k < HRTF_SH_CHANNELS; k++ )
2548 : {
2549 3200368560 : *lRealp += hrtfShCoeffsReInt[0][k][bin] * shVec[k];
2550 3200368560 : *lImagp += hrtfShCoeffsImInt[0][k][bin] * shVec[k];
2551 3200368560 : *rRealp += hrtfShCoeffsReInt[1][k][bin] * shVec[k];
2552 3200368560 : *rImagp += hrtfShCoeffsImInt[1][k][bin] * shVec[k];
2553 :
2554 3200368560 : gainCache->shVec[k] = shVec[k];
2555 : }
2556 : }
2557 :
2558 645813497 : return;
2559 : }
2560 :
2561 :
2562 : /*-------------------------------------------------------------------------
2563 : * configure_reqularization_factor()
2564 : *
2565 : * Configure regularization factor for the mixing matrix generation of the
2566 : * parametric binauralizer using IVAS codec format and current bitrate.
2567 : *------------------------------------------------------------------------*/
2568 :
2569 : /*! r: Configured reqularization factor value */
2570 64167 : float configure_reqularization_factor(
2571 : const IVAS_FORMAT ivas_format, /* i : IVAS format */
2572 : const int32_t ivas_total_brate /* i : IVAS total bitrate */
2573 : )
2574 : {
2575 : float reqularizationFactor;
2576 64167 : reqularizationFactor = 1.0f; /* Default value */
2577 :
2578 64167 : if ( ivas_format == MASA_FORMAT )
2579 : {
2580 22525 : if ( ivas_total_brate >= IVAS_160k )
2581 : {
2582 1436 : reqularizationFactor = 0.4f;
2583 : }
2584 21089 : else if ( ivas_total_brate == IVAS_128k )
2585 : {
2586 996 : reqularizationFactor = 0.5f;
2587 : }
2588 20093 : else if ( ivas_total_brate == IVAS_96k )
2589 : {
2590 468 : reqularizationFactor = 0.6f;
2591 : }
2592 19625 : else if ( ivas_total_brate >= IVAS_64k )
2593 : {
2594 973 : reqularizationFactor = 0.8f;
2595 : }
2596 : else
2597 : {
2598 18652 : reqularizationFactor = 1.0f;
2599 : }
2600 : }
2601 :
2602 64167 : if ( ivas_format == MC_FORMAT ) /* This is always McMASA for parametric binauralizer. */
2603 : {
2604 2087 : if ( ivas_total_brate >= IVAS_96k )
2605 : {
2606 33 : reqularizationFactor = 0.4f;
2607 : }
2608 2054 : else if ( ivas_total_brate >= IVAS_80k )
2609 : {
2610 66 : reqularizationFactor = 0.5f;
2611 : }
2612 1988 : else if ( ivas_total_brate >= IVAS_64k )
2613 : {
2614 84 : reqularizationFactor = 0.7f;
2615 : }
2616 1904 : else if ( ivas_total_brate >= IVAS_48k )
2617 : {
2618 99 : reqularizationFactor = 0.8f;
2619 : }
2620 : else
2621 : {
2622 1805 : reqularizationFactor = 1.0f;
2623 : }
2624 : }
2625 :
2626 : /* For SBA and parametric ISM, currently in default value of 1.0f. */
2627 :
2628 64167 : return reqularizationFactor;
2629 : }
2630 :
2631 :
2632 : /*-------------------------------------------------------------------*
2633 : * ivas_omasa_preProcessStereoTransportsForEditedObjects()
2634 : *
2635 : *
2636 : *-------------------------------------------------------------------*/
2637 :
2638 893813 : void ivas_omasa_preProcessStereoTransportsForEditedObjects(
2639 : Decoder_Struct *st_ivas,
2640 : float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
2641 : float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
2642 : const int16_t nBins,
2643 : const int16_t subframe )
2644 : {
2645 : int16_t bin, ch, inCh, outCh, ismDirIndex, slot, band_idx, bin_lo, bin_hi, max_band, n_ism;
2646 : SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom;
2647 : MASA_ISM_DATA_HANDLE hMasaIsmData;
2648 : PARAM_ISM_DEC_HANDLE hParamIsmDec;
2649 : uint8_t enableCentering;
2650 : int16_t dirac_read_idx;
2651 : int16_t nSlots;
2652 : float panGainsOut[4][2];
2653 : float panGainsIn[4][2];
2654 : float panEnesOut[4][2];
2655 : float panEnesIn[4][2];
2656 : uint8_t ismGainEdited[4];
2657 : uint8_t ismDirEdited[4];
2658 : uint8_t masaGainEdited;
2659 : uint8_t masaIsmMode;
2660 :
2661 893813 : hSpatParamRendCom = st_ivas->hSpatParamRendCom;
2662 893813 : hMasaIsmData = st_ivas->hMasaIsmData;
2663 893813 : hParamIsmDec = st_ivas->hParamIsmDec;
2664 :
2665 893813 : if ( st_ivas->ivas_format == MASA_ISM_FORMAT )
2666 : {
2667 661905 : masaIsmMode = 1u;
2668 : }
2669 : else
2670 : {
2671 231908 : masaIsmMode = 0u;
2672 : }
2673 :
2674 893813 : 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 )
2675 : {
2676 62088 : enableCentering = 0;
2677 : }
2678 : else
2679 : {
2680 831725 : enableCentering = 1;
2681 : }
2682 :
2683 893813 : if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC || st_ivas->ivas_format == ISM_FORMAT )
2684 : {
2685 590396 : n_ism = st_ivas->nchan_ism;
2686 : }
2687 : else
2688 : {
2689 303417 : n_ism = hSpatParamRendCom->numIsmDirections;
2690 : }
2691 :
2692 3588697 : for ( ismDirIndex = 0; ismDirIndex < n_ism; ismDirIndex++ )
2693 : {
2694 2694884 : ismGainEdited[ismDirIndex] = hMasaIsmData->ism_gain_is_edited[ismDirIndex];
2695 2694884 : ismDirEdited[ismDirIndex] = hMasaIsmData->ism_dir_is_edited[ismDirIndex];
2696 : }
2697 893813 : masaGainEdited = hMasaIsmData->masa_gain_is_edited;
2698 :
2699 : /* Bypass processing until first object is moved or gained */
2700 893813 : if ( hMasaIsmData->objectsEdited == 0 )
2701 : {
2702 3328309 : for ( ismDirIndex = 0; ismDirIndex < n_ism; ismDirIndex++ )
2703 : {
2704 2488166 : if ( ismDirEdited[ismDirIndex] )
2705 : {
2706 1827 : hMasaIsmData->objectsEdited = 1;
2707 : }
2708 :
2709 2488166 : if ( ismGainEdited[ismDirIndex] )
2710 : {
2711 1722 : hMasaIsmData->objectsEdited = 1;
2712 : }
2713 : }
2714 :
2715 840143 : if ( masaGainEdited )
2716 : {
2717 6 : hMasaIsmData->objectsEdited = 1;
2718 : }
2719 :
2720 840143 : if ( hMasaIsmData->objectsEdited == 0 )
2721 : {
2722 : /* No objects have moved so far */
2723 839684 : return;
2724 : }
2725 : }
2726 :
2727 : /* OMASA gaining for discrete OMASA mode with stereo_param/bin_room_param renderer */
2728 54129 : if ( ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) && st_ivas->ism_mode == ISM_MASA_MODE_DISC )
2729 : {
2730 : /* ISM gaining */
2731 0 : for ( ch = 0; ch < n_ism; ch++ )
2732 : {
2733 0 : if ( st_ivas->hMasaIsmData->ism_gain_is_edited[ch] )
2734 : {
2735 0 : for ( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ )
2736 : {
2737 : float gain;
2738 0 : gain = st_ivas->hMasaIsmData->gain_ism_edited[ch];
2739 0 : v_multc( inRe[ch + 2][slot], gain, inRe[ch + 2][slot], nBins );
2740 0 : v_multc( inIm[ch + 2][slot], gain, inIm[ch + 2][slot], nBins );
2741 : }
2742 : }
2743 : }
2744 :
2745 : /* MASA gaining */
2746 0 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
2747 : {
2748 0 : if ( masaGainEdited )
2749 : {
2750 0 : for ( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ )
2751 : {
2752 : float gain_masa;
2753 0 : gain_masa = st_ivas->hMasaIsmData->gain_masa_edited;
2754 0 : v_multc( inRe[ch][slot], gain_masa, inRe[ch][slot], nBins );
2755 0 : v_multc( inIm[ch][slot], gain_masa, inIm[ch][slot], nBins );
2756 : }
2757 : }
2758 : }
2759 : }
2760 54129 : else if ( st_ivas->ivas_format == ISM_FORMAT && st_ivas->hISMDTX.dtx_flag ) /* If dtx on, perform just the smoothing of the processing gains */
2761 0 : {
2762 : float totalTargetEne;
2763 : float ismPreprocMtxNew[2][2];
2764 : float ismPreprocMtxIncrement[2][2];
2765 : float nSlotDiv;
2766 : float outSlotRe[2][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
2767 : float outSlotIm[2][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
2768 : float eqVal;
2769 :
2770 0 : nSlots = hSpatParamRendCom->subframe_nbslots[subframe];
2771 0 : nSlotDiv = 1.0f / ( (float) nSlots );
2772 :
2773 : /* Use diagonal mixing matrix as the instant mixing matrix, to slowly fade away the editing during dtx */
2774 0 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
2775 : {
2776 0 : ismPreprocMtxNew[ch][ch] = 1.0f;
2777 0 : ismPreprocMtxNew[1 - ch][ch] = 0.0f;
2778 : }
2779 :
2780 : /* Determine the highest band */
2781 0 : max_band = 0;
2782 0 : while ( max_band < MAX_PARAM_ISM_NBANDS && hParamIsmDec->hParamIsm->band_grouping[max_band] < nBins )
2783 : {
2784 0 : max_band++;
2785 : }
2786 :
2787 : /* Init out array */
2788 0 : for ( slot = 0; slot < nSlots; slot++ )
2789 : {
2790 0 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
2791 : {
2792 0 : set_zero( outSlotRe[ch][slot], CLDFB_NO_CHANNELS_MAX );
2793 0 : set_zero( outSlotIm[ch][slot], CLDFB_NO_CHANNELS_MAX );
2794 : }
2795 : }
2796 :
2797 : /* Perform the processing in frequency bands */
2798 0 : for ( band_idx = 0; band_idx < max_band; band_idx++ )
2799 : {
2800 0 : bin_lo = hParamIsmDec->hParamIsm->band_grouping[band_idx];
2801 0 : bin_hi = min( hParamIsmDec->hParamIsm->band_grouping[band_idx + 1], nBins );
2802 :
2803 : /* Determine transport energies */
2804 0 : totalTargetEne = 0.0f;
2805 0 : for ( slot = 0; slot < nSlots; slot++ )
2806 : {
2807 0 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
2808 : {
2809 0 : for ( bin = bin_lo; bin < bin_hi; bin++ )
2810 : {
2811 0 : totalTargetEne += inRe[ch][slot][bin] * inRe[ch][slot][bin];
2812 0 : totalTargetEne += inIm[ch][slot][bin] * inIm[ch][slot][bin];
2813 : }
2814 : }
2815 : }
2816 :
2817 : /* Get increment value for temporal interpolation */
2818 0 : for ( inCh = 0; inCh < BINAURAL_CHANNELS; inCh++ )
2819 : {
2820 0 : for ( outCh = 0; outCh < BINAURAL_CHANNELS; outCh++ )
2821 : {
2822 0 : ismPreprocMtxIncrement[outCh][inCh] = ( ismPreprocMtxNew[outCh][inCh] - hMasaIsmData->ismPreprocMatrix[outCh][inCh][band_idx] ) * nSlotDiv;
2823 : }
2824 : }
2825 :
2826 : /* Mix signals */
2827 0 : hMasaIsmData->preprocEneTarget[band_idx] *= STEREO_PREPROCESS_IIR_FACTOR;
2828 0 : hMasaIsmData->preprocEneRealized[band_idx] *= STEREO_PREPROCESS_IIR_FACTOR;
2829 0 : hMasaIsmData->preprocEneTarget[band_idx] += totalTargetEne;
2830 :
2831 0 : for ( outCh = 0; outCh < BINAURAL_CHANNELS; outCh++ )
2832 : {
2833 0 : for ( slot = 0; slot < nSlots; slot++ )
2834 : {
2835 0 : for ( inCh = 0; inCh < BINAURAL_CHANNELS; inCh++ )
2836 : {
2837 0 : hMasaIsmData->ismPreprocMatrix[outCh][inCh][band_idx] += ismPreprocMtxIncrement[outCh][inCh];
2838 0 : for ( bin = bin_lo; bin < bin_hi; bin++ )
2839 : {
2840 0 : outSlotRe[outCh][slot][bin] += inRe[inCh][slot][bin] * hMasaIsmData->ismPreprocMatrix[outCh][inCh][band_idx];
2841 0 : outSlotIm[outCh][slot][bin] += inIm[inCh][slot][bin] * hMasaIsmData->ismPreprocMatrix[outCh][inCh][band_idx];
2842 : }
2843 : }
2844 :
2845 0 : for ( bin = bin_lo; bin < bin_hi; bin++ )
2846 : {
2847 0 : hMasaIsmData->preprocEneRealized[band_idx] += ( outSlotRe[outCh][slot][bin] * outSlotRe[outCh][slot][bin] ) + ( outSlotIm[outCh][slot][bin] * outSlotIm[outCh][slot][bin] );
2848 : }
2849 : }
2850 : }
2851 :
2852 0 : eqVal = fminf( 4.0f, sqrtf( hMasaIsmData->preprocEneTarget[band_idx] / fmaxf( 1e-12f, hMasaIsmData->preprocEneRealized[band_idx] ) ) );
2853 :
2854 0 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
2855 : {
2856 0 : for ( slot = 0; slot < nSlots; slot++ )
2857 : {
2858 0 : for ( bin = bin_lo; bin < bin_hi; bin++ )
2859 : {
2860 0 : inRe[ch][slot][bin] = outSlotRe[ch][slot][bin] * eqVal;
2861 0 : inIm[ch][slot][bin] = outSlotIm[ch][slot][bin] * eqVal;
2862 : }
2863 : }
2864 : }
2865 : }
2866 : }
2867 : else /* Other processing modes */
2868 : {
2869 : float subframeEne;
2870 : float subframeEneCh[2];
2871 : float normEnes[2];
2872 : float ratioAccOrig;
2873 : float ratioAccNew;
2874 : float ratio;
2875 : float ismEneThis;
2876 : float ismTargetEneThis;
2877 : float ismTargetEneThisCh[2];
2878 : float totalTargetEneCh[2];
2879 : float totalTargetEne;
2880 : float masaTargetEneThisCh[2];
2881 : float ismPreprocMtxNew[2][2];
2882 : float ismPreprocMtxIncrement[2][2];
2883 : float eneMove[2];
2884 : float enePreserve[2];
2885 : float ismRatioAcc;
2886 : float remainderNormEne;
2887 : float centeringFactor;
2888 : float eneMoveThis;
2889 : float enePreserveThis;
2890 : float normVal;
2891 : float eqVal;
2892 : float outSlotRe[2][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
2893 : float outSlotIm[2][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
2894 : float newRatios[6];
2895 : float gainIsmThis;
2896 : float gainMasaPow2;
2897 : float nSlotDiv;
2898 : float tempDivisor;
2899 : float masaEneThisCh[2];
2900 : float ratioAccNewDivisor;
2901 :
2902 54129 : gainMasaPow2 = 1.0f;
2903 54129 : if ( masaGainEdited )
2904 : {
2905 15792 : gainMasaPow2 = hMasaIsmData->gain_masa_edited;
2906 15792 : gainMasaPow2 *= gainMasaPow2;
2907 : }
2908 :
2909 54129 : nSlots = hSpatParamRendCom->subframe_nbslots[subframe];
2910 54129 : dirac_read_idx = hSpatParamRendCom->render_to_md_map[subframe];
2911 54129 : nSlotDiv = 1.0f / ( (float) nSlots );
2912 :
2913 : /* Determine panning gains and energies for each object */
2914 262677 : for ( ismDirIndex = 0; ismDirIndex < n_ism; ismDirIndex++ )
2915 : {
2916 : /* Get input and output panning gains */
2917 208548 : ivas_get_stereo_panning_gains( hMasaIsmData->azimuth_ism[ismDirIndex][dirac_read_idx],
2918 208548 : hMasaIsmData->elevation_ism[ismDirIndex][dirac_read_idx],
2919 208548 : panGainsIn[ismDirIndex] );
2920 :
2921 208548 : if ( ismDirEdited[ismDirIndex] )
2922 : {
2923 206052 : ivas_get_stereo_panning_gains( hMasaIsmData->azimuth_ism_edited[ismDirIndex],
2924 206052 : hMasaIsmData->elevation_ism_edited[ismDirIndex],
2925 206052 : panGainsOut[ismDirIndex] );
2926 : }
2927 : else
2928 : {
2929 : /* When not edited, input and output pan gains are the same */
2930 7488 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
2931 : {
2932 4992 : panGainsOut[ismDirIndex][ch] = panGainsIn[ismDirIndex][ch];
2933 : }
2934 : }
2935 :
2936 : /* Determine pan enes */
2937 625644 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
2938 : {
2939 417096 : panEnesOut[ismDirIndex][ch] = panGainsOut[ismDirIndex][ch] * panGainsOut[ismDirIndex][ch];
2940 417096 : panEnesIn[ismDirIndex][ch] = panGainsIn[ismDirIndex][ch] * panGainsIn[ismDirIndex][ch];
2941 : }
2942 : }
2943 :
2944 : /* Determine the highest band */
2945 54129 : max_band = 0;
2946 54129 : if ( masaIsmMode )
2947 : {
2948 399600 : while ( max_band < MASA_FREQUENCY_BANDS && MASA_band_grouping_24[max_band] < nBins )
2949 : {
2950 383616 : max_band++;
2951 : }
2952 : }
2953 : else
2954 : {
2955 457740 : while ( max_band < MAX_PARAM_ISM_NBANDS && hParamIsmDec->hParamIsm->band_grouping[max_band] < nBins )
2956 : {
2957 419595 : max_band++;
2958 : }
2959 : }
2960 :
2961 : /* Init out array */
2962 262017 : for ( slot = 0; slot < nSlots; slot++ )
2963 : {
2964 623664 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
2965 : {
2966 415776 : set_zero( outSlotRe[ch][slot], CLDFB_NO_CHANNELS_MAX );
2967 415776 : set_zero( outSlotIm[ch][slot], CLDFB_NO_CHANNELS_MAX );
2968 : }
2969 : }
2970 :
2971 : /* Perform the processing in frequency bands */
2972 857340 : for ( band_idx = 0; band_idx < max_band; band_idx++ )
2973 : {
2974 803211 : ratioAccOrig = 0.0f;
2975 803211 : ratioAccNew = 0.0f;
2976 803211 : ismRatioAcc = 0.0f;
2977 :
2978 803211 : set_zero( subframeEneCh, 2 );
2979 803211 : set_zero( ismPreprocMtxNew[0], 2 );
2980 803211 : set_zero( ismPreprocMtxNew[1], 2 );
2981 803211 : set_zero( eneMove, 2 );
2982 803211 : set_zero( enePreserve, 2 );
2983 803211 : if ( masaIsmMode )
2984 : {
2985 383616 : bin_lo = MASA_band_grouping_24[band_idx];
2986 383616 : bin_hi = min( MASA_band_grouping_24[band_idx + 1], nBins );
2987 : }
2988 : else
2989 : {
2990 419595 : bin_lo = hParamIsmDec->hParamIsm->band_grouping[band_idx];
2991 419595 : bin_hi = min( hParamIsmDec->hParamIsm->band_grouping[band_idx + 1], nBins );
2992 : }
2993 :
2994 : /* Determine transport normalized energies and subframe energy */
2995 3921147 : for ( slot = 0; slot < nSlots; slot++ )
2996 : {
2997 9353808 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
2998 : {
2999 31182432 : for ( bin = bin_lo; bin < bin_hi; bin++ )
3000 : {
3001 24946560 : subframeEneCh[ch] += inRe[ch][slot][bin] * inRe[ch][slot][bin];
3002 24946560 : subframeEneCh[ch] += inIm[ch][slot][bin] * inIm[ch][slot][bin];
3003 : }
3004 : }
3005 : }
3006 803211 : subframeEne = subframeEneCh[0] + subframeEneCh[1];
3007 803211 : totalTargetEneCh[0] = subframeEneCh[0];
3008 803211 : totalTargetEneCh[1] = subframeEneCh[1];
3009 803211 : masaEneThisCh[0] = subframeEneCh[0];
3010 803211 : masaEneThisCh[1] = subframeEneCh[1];
3011 :
3012 : /* Gain editing */
3013 : /* For each object, estimate new target energy per channel based on the applied gain */
3014 3824823 : for ( ismDirIndex = 0; ismDirIndex < n_ism; ismDirIndex++ )
3015 : {
3016 3021612 : ratio = hMasaIsmData->energy_ratio_ism[ismDirIndex][dirac_read_idx][bin_lo];
3017 3021612 : ratioAccOrig += ratio;
3018 :
3019 : /* Calculate MASA energy as a residual of original channel energies subtracted with ISM energies */
3020 9064836 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
3021 : {
3022 6043224 : masaEneThisCh[ch] -= panEnesIn[ismDirIndex][ch] * ratio * subframeEne;
3023 : }
3024 :
3025 : /* Calculate target energy, gained ratio for accumulation, and transports gains, if ism gain is edited */
3026 3021612 : if ( ismGainEdited[ismDirIndex] )
3027 : {
3028 2787666 : gainIsmThis = hMasaIsmData->gain_ism_edited[ismDirIndex];
3029 : /* ISM original energy */
3030 2787666 : ismEneThis = ratio * subframeEne;
3031 :
3032 : /* ISM target energy */
3033 2787666 : ismTargetEneThis = ( gainIsmThis * gainIsmThis ) * ismEneThis;
3034 :
3035 2787666 : ratio *= gainIsmThis * gainIsmThis;
3036 :
3037 : /* Determine panning energies and channel target energies */
3038 8362998 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
3039 : {
3040 5575332 : ismTargetEneThisCh[ch] = panEnesIn[ismDirIndex][ch] * ismTargetEneThis; /* Ism target energy per channel */
3041 5575332 : totalTargetEneCh[ch] -= panEnesIn[ismDirIndex][ch] * ismEneThis; /* Reduce original ism energy */
3042 5575332 : totalTargetEneCh[ch] += ismTargetEneThisCh[ch]; /* Add ism target energy per channel */
3043 : }
3044 :
3045 : /* If separated ism edited, apply gain directly to the separated ism */
3046 2787666 : if ( ismDirIndex == hMasaIsmData->idx_separated_ism )
3047 : {
3048 : /* Separated object gaining is done elsewhere with DIRAC renderer */
3049 369504 : if ( st_ivas->renderer_type != RENDERER_DIRAC )
3050 : {
3051 : /* Gain transport channel of separated ism */
3052 1847520 : for ( slot = 0; slot < nSlots; slot++ )
3053 : {
3054 5173056 : for ( bin = bin_lo; bin < bin_hi; bin++ )
3055 : {
3056 3695040 : inRe[2][slot][bin] = gainIsmThis * inRe[2][slot][bin];
3057 3695040 : inIm[2][slot][bin] = gainIsmThis * inIm[2][slot][bin];
3058 : }
3059 : }
3060 : }
3061 : }
3062 : }
3063 3021612 : ratioAccNew += ratio;
3064 : }
3065 :
3066 803211 : if ( masaIsmMode )
3067 : {
3068 : /* MASA original ratios */
3069 383616 : ratio = hSpatParamRendCom->energy_ratio1[dirac_read_idx][bin_lo] + hSpatParamRendCom->energy_ratio2[dirac_read_idx][bin_lo];
3070 383616 : ratioAccOrig += ratio;
3071 :
3072 : /* Estimate MASA original energies and determine adjusted target energies and gained ratio for accumulation, if a gain is applied to MASA */
3073 383616 : if ( masaGainEdited )
3074 : {
3075 : /* Gained MASA ratio */
3076 379008 : ratio *= gainMasaPow2;
3077 :
3078 : /* Calculate MASA target energies and add to total target energy estimation */
3079 1137024 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
3080 : {
3081 758016 : masaEneThisCh[ch] = fmaxf( masaEneThisCh[ch], 0.0f ); /* MASA original energy per channel */
3082 758016 : masaTargetEneThisCh[ch] = gainMasaPow2 * masaEneThisCh[ch]; /* MASA target energy per channel */
3083 758016 : totalTargetEneCh[ch] -= masaEneThisCh[ch]; /* Reduce original energy per channel */
3084 758016 : totalTargetEneCh[ch] += masaTargetEneThisCh[ch]; /* Add target energy per channel */
3085 : }
3086 : }
3087 :
3088 383616 : ratioAccNew += ratio;
3089 : }
3090 :
3091 : /* Limit target energies to non-negative values */
3092 2409633 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
3093 : {
3094 1606422 : totalTargetEneCh[ch] = max( totalTargetEneCh[ch], 0.0f );
3095 : }
3096 :
3097 : /* due to rounding, the sum may exceed 1.0f ever so slightly, so clip it */
3098 803211 : ratioAccOrig = min( ratioAccOrig, 1.0f );
3099 803211 : if ( masaGainEdited )
3100 : {
3101 379008 : ratioAccNew += gainMasaPow2 * ( 1.0f - ratioAccOrig );
3102 : }
3103 : else
3104 : {
3105 424203 : ratioAccNew += ( 1.0f - ratioAccOrig );
3106 : }
3107 :
3108 803211 : ratioAccNewDivisor = 1.0f / fmaxf( 1e-12f, ratioAccNew ); /* New target total energy ratio divider */
3109 :
3110 : /* Determine and process object energy ratios based on gaining */
3111 3824823 : for ( ismDirIndex = 0; ismDirIndex < n_ism; ismDirIndex++ )
3112 : {
3113 3021612 : newRatios[ismDirIndex + 2] = hMasaIsmData->energy_ratio_ism[ismDirIndex][dirac_read_idx][bin_lo]; /* Determine original object energy ratio */
3114 3021612 : if ( ismGainEdited[ismDirIndex] )
3115 : {
3116 2787666 : gainIsmThis = hMasaIsmData->gain_ism_edited[ismDirIndex];
3117 2787666 : newRatios[ismDirIndex + 2] *= ( gainIsmThis * gainIsmThis ); /* Gain original object energy ratio, if edited */
3118 : }
3119 3021612 : newRatios[ismDirIndex + 2] *= ratioAccNewDivisor; /* Divide with new target total ratio */
3120 : }
3121 :
3122 : /* Determine and process MASA energy ratios based on gaining */
3123 803211 : newRatios[0] = hSpatParamRendCom->energy_ratio1[dirac_read_idx][bin_lo];
3124 803211 : newRatios[1] = hSpatParamRendCom->energy_ratio2[dirac_read_idx][bin_lo];
3125 803211 : if ( masaGainEdited )
3126 : {
3127 379008 : newRatios[0] *= gainMasaPow2;
3128 379008 : newRatios[1] *= gainMasaPow2;
3129 : }
3130 803211 : newRatios[0] *= ratioAccNewDivisor;
3131 803211 : newRatios[1] *= ratioAccNewDivisor;
3132 :
3133 : /* Set adjusted energy ratios */
3134 4050951 : for ( bin = bin_lo; bin < bin_hi; bin++ )
3135 : {
3136 15760620 : for ( ismDirIndex = 0; ismDirIndex < n_ism; ismDirIndex++ )
3137 : {
3138 12512880 : hMasaIsmData->energy_ratio_ism[ismDirIndex][dirac_read_idx][bin] = newRatios[ismDirIndex + 2];
3139 : }
3140 3247740 : hSpatParamRendCom->energy_ratio1[dirac_read_idx][bin] = newRatios[0];
3141 3247740 : hSpatParamRendCom->energy_ratio2[dirac_read_idx][bin] = newRatios[1];
3142 : }
3143 :
3144 : /* Direction editing */
3145 : /* Determine new energetic values after gaining */
3146 803211 : totalTargetEne = totalTargetEneCh[0] + totalTargetEneCh[1];
3147 803211 : tempDivisor = 1.0f / fmaxf( 1e-12f, totalTargetEne );
3148 803211 : normEnes[0] = totalTargetEneCh[0] * tempDivisor;
3149 803211 : normEnes[1] = totalTargetEneCh[1] * tempDivisor;
3150 :
3151 : /* For each ismDir, determine moved and preserve energy ratio per channel */
3152 3824823 : for ( ismDirIndex = 0; ismDirIndex < n_ism; ismDirIndex++ )
3153 : {
3154 3021612 : ratio = hMasaIsmData->energy_ratio_ism[ismDirIndex][dirac_read_idx][bin_lo];
3155 :
3156 3021612 : ismRatioAcc += ratio;
3157 :
3158 3021612 : if ( enableCentering )
3159 : {
3160 3021612 : centeringFactor = fmaxf( 0.0f, 2.0f * fabsf( panEnesIn[ismDirIndex][0] - panEnesOut[ismDirIndex][0] ) - 1.0f );
3161 9064836 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
3162 : {
3163 6043224 : panEnesOut[ismDirIndex][ch] *= ( 1.0f - centeringFactor );
3164 6043224 : panEnesOut[ismDirIndex][ch] += 0.5f * centeringFactor;
3165 : }
3166 : }
3167 :
3168 9064836 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
3169 : {
3170 6043224 : eneMoveThis = fmaxf( 0.0f, panEnesIn[ismDirIndex][ch] - panEnesOut[ismDirIndex][ch] );
3171 6043224 : enePreserveThis = panEnesIn[ismDirIndex][ch] - eneMoveThis;
3172 :
3173 6043224 : eneMove[ch] += ratio * eneMoveThis;
3174 6043224 : enePreserve[ch] += ratio * enePreserveThis;
3175 :
3176 : /* Subtract object parts from normEnes */
3177 6043224 : normEnes[ch] -= panEnesIn[ismDirIndex][ch] * ratio;
3178 : }
3179 : }
3180 :
3181 : /* Any remaining (non-object) energy is set to be preserved at both channels */
3182 803211 : remainderNormEne = fmaxf( 0.0f, ( 1.0f - ismRatioAcc ) - normEnes[0] - normEnes[1] );
3183 :
3184 : /* Normalize */
3185 2409633 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
3186 : {
3187 1606422 : enePreserve[ch] += fmaxf( 0.0f, normEnes[ch] + remainderNormEne / 2.0f );
3188 1606422 : normVal = 1.0f / fmaxf( EPSILON, eneMove[ch] + enePreserve[ch] );
3189 1606422 : normVal *= fminf( 10.0f, totalTargetEneCh[ch] / fmaxf( EPSILON, subframeEneCh[ch] ) );
3190 1606422 : eneMove[ch] *= normVal;
3191 1606422 : enePreserve[ch] *= normVal;
3192 : }
3193 :
3194 : /* Temporally average target energy */
3195 803211 : hMasaIsmData->eneOrigIIR[band_idx] *= STEREO_PREPROCESS_IIR_FACTOR;
3196 803211 : hMasaIsmData->eneOrigIIR[band_idx] += totalTargetEne;
3197 :
3198 : /* Temporally average energy moving and preserving, and generate the transport signal preprocessing matrix for
3199 : * gaining objects and moving objects between left and right */
3200 2409633 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
3201 : {
3202 1606422 : hMasaIsmData->eneMoveIIR[ch][band_idx] *= STEREO_PREPROCESS_IIR_FACTOR;
3203 1606422 : hMasaIsmData->eneMoveIIR[ch][band_idx] += eneMove[ch] * totalTargetEne;
3204 1606422 : hMasaIsmData->enePreserveIIR[ch][band_idx] *= STEREO_PREPROCESS_IIR_FACTOR;
3205 1606422 : hMasaIsmData->enePreserveIIR[ch][band_idx] += enePreserve[ch] * totalTargetEne;
3206 1606422 : normVal = 1.0f / fmaxf( EPSILON, hMasaIsmData->eneOrigIIR[band_idx] );
3207 1606422 : ismPreprocMtxNew[ch][ch] = fminf( 4.0f, sqrtf( hMasaIsmData->enePreserveIIR[ch][band_idx] * normVal ) );
3208 1606422 : ismPreprocMtxNew[1 - ch][ch] = fminf( 4.0f, sqrtf( hMasaIsmData->eneMoveIIR[ch][band_idx] * normVal ) );
3209 : }
3210 :
3211 : /* Get increment value for temporal interpolation */
3212 2409633 : for ( inCh = 0; inCh < BINAURAL_CHANNELS; inCh++ )
3213 : {
3214 4819266 : for ( outCh = 0; outCh < BINAURAL_CHANNELS; outCh++ )
3215 : {
3216 3212844 : ismPreprocMtxIncrement[outCh][inCh] = ( ismPreprocMtxNew[outCh][inCh] - hMasaIsmData->ismPreprocMatrix[outCh][inCh][band_idx] ) * nSlotDiv;
3217 : }
3218 : }
3219 :
3220 : /* Mix signals */
3221 803211 : hMasaIsmData->preprocEneTarget[band_idx] *= STEREO_PREPROCESS_IIR_FACTOR;
3222 803211 : hMasaIsmData->preprocEneRealized[band_idx] *= STEREO_PREPROCESS_IIR_FACTOR;
3223 803211 : hMasaIsmData->preprocEneTarget[band_idx] += totalTargetEne;
3224 :
3225 2409633 : for ( outCh = 0; outCh < BINAURAL_CHANNELS; outCh++ )
3226 : {
3227 7842294 : for ( slot = 0; slot < nSlots; slot++ )
3228 : {
3229 18707616 : for ( inCh = 0; inCh < BINAURAL_CHANNELS; inCh++ )
3230 : {
3231 12471744 : hMasaIsmData->ismPreprocMatrix[outCh][inCh][band_idx] += ismPreprocMtxIncrement[outCh][inCh];
3232 62364864 : for ( bin = bin_lo; bin < bin_hi; bin++ )
3233 : {
3234 49893120 : outSlotRe[outCh][slot][bin] += inRe[inCh][slot][bin] * hMasaIsmData->ismPreprocMatrix[outCh][inCh][band_idx];
3235 49893120 : outSlotIm[outCh][slot][bin] += inIm[inCh][slot][bin] * hMasaIsmData->ismPreprocMatrix[outCh][inCh][band_idx];
3236 : }
3237 : }
3238 :
3239 31182432 : for ( bin = bin_lo; bin < bin_hi; bin++ )
3240 : {
3241 24946560 : hMasaIsmData->preprocEneRealized[band_idx] += ( outSlotRe[outCh][slot][bin] * outSlotRe[outCh][slot][bin] ) + ( outSlotIm[outCh][slot][bin] * outSlotIm[outCh][slot][bin] );
3242 : }
3243 : }
3244 : }
3245 :
3246 803211 : eqVal = fminf( 4.0f, sqrtf( hMasaIsmData->preprocEneTarget[band_idx] / fmaxf( 1e-12f, hMasaIsmData->preprocEneRealized[band_idx] ) ) );
3247 :
3248 2409633 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
3249 : {
3250 7842294 : for ( slot = 0; slot < nSlots; slot++ )
3251 : {
3252 31182432 : for ( bin = bin_lo; bin < bin_hi; bin++ )
3253 : {
3254 24946560 : inRe[ch][slot][bin] = outSlotRe[ch][slot][bin] * eqVal;
3255 24946560 : inIm[ch][slot][bin] = outSlotIm[ch][slot][bin] * eqVal;
3256 : }
3257 : }
3258 : }
3259 : }
3260 :
3261 54129 : if ( !masaIsmMode )
3262 : {
3263 : int16_t obj_idx1, obj_idx2;
3264 :
3265 457740 : for ( band_idx = 0; band_idx < hParamIsmDec->hParamIsm->nbands; band_idx++ )
3266 : {
3267 419595 : bin_lo = hParamIsmDec->hParamIsm->band_grouping[band_idx];
3268 419595 : bin_hi = hParamIsmDec->hParamIsm->band_grouping[band_idx + 1];
3269 :
3270 419595 : obj_idx1 = hParamIsmDec->hParamIsm->obj_indices[band_idx][0][0];
3271 419595 : obj_idx2 = hParamIsmDec->hParamIsm->obj_indices[band_idx][0][1];
3272 :
3273 2708295 : for ( bin = bin_lo; bin < bin_hi; bin++ )
3274 : {
3275 2288700 : hSpatParamRendCom->energy_ratio1[dirac_read_idx][bin] = hMasaIsmData->energy_ratio_ism[obj_idx1][dirac_read_idx][bin];
3276 2288700 : hSpatParamRendCom->energy_ratio2[dirac_read_idx][bin] = hMasaIsmData->energy_ratio_ism[obj_idx2][dirac_read_idx][bin];
3277 : }
3278 : }
3279 : }
3280 : }
3281 :
3282 54129 : return;
3283 : }
3284 :
3285 :
3286 708664 : static void ivas_masa_ext_rend_parambin_internal(
3287 : MASA_EXT_REND_HANDLE hMasaExtRend,
3288 : COMBINED_ORIENTATION_HANDLE hCombinedOrientationData,
3289 : float *output_f[],
3290 : const int16_t subframe,
3291 : const SPLIT_REND_WRAPPER *hSplitRendWrapper,
3292 : float Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
3293 : float Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] )
3294 : {
3295 : DIRAC_DEC_BIN_HANDLE hDiracDecBin;
3296 : SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom;
3297 : PARAMBIN_REND_CONFIG config_data;
3298 : int16_t slot, ch, numInChannels;
3299 : float Cldfb_RealBuffer_in[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
3300 : float Cldfb_ImagBuffer_in[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
3301 : float Rmat[3][3];
3302 : int16_t max_band_decorr;
3303 : int16_t nBins;
3304 : int16_t i, j;
3305 : int16_t nchan_transport;
3306 :
3307 : int16_t pos_idx;
3308 : const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData;
3309 : float tmp_Cldfb_out_re[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
3310 : float tmp_Cldfb_out_im[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
3311 :
3312 : /* 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 */
3313 : float reverbRe[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
3314 : float reverbIm[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
3315 : float decorrRe[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
3316 : float decorrIm[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
3317 : float subFrameTotalEne[CLDFB_NO_CHANNELS_MAX];
3318 : float IIReneLimiter[CLDFB_NO_CHANNELS_MAX];
3319 :
3320 708664 : hDiracDecBin = hMasaExtRend->hDiracDecBin[0];
3321 708664 : assert( hDiracDecBin );
3322 708664 : hSpatParamRendCom = hMasaExtRend->hSpatParamRendCom;
3323 708664 : nBins = hSpatParamRendCom->num_freq_bands;
3324 :
3325 : /* Setup internal config. MASA EXT renderer is quite strict. */
3326 708664 : config_data.separateCenterChannelRendering = 0;
3327 708664 : config_data.ivas_format = MASA_FORMAT;
3328 708664 : config_data.mc_mode = MC_MODE_NONE;
3329 708664 : config_data.ivas_total_brate = IVAS_512k; /* Maximum bitrate set for external renderer */
3330 708664 : config_data.nchan_transport = hMasaExtRend->nchan_input;
3331 708664 : config_data.qualityBasedSmFactor = 1.0f;
3332 708664 : config_data.processReverb = hMasaExtRend->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ? 1 : 0;
3333 708664 : config_data.ism_mode = ISM_MODE_NONE;
3334 :
3335 : /* Set nchan_transport to number of transport channels in MASA input */
3336 708664 : nchan_transport = hMasaExtRend->nchan_input;
3337 :
3338 : /* The input channel number at this processing function (not nchan_transport) */
3339 708664 : numInChannels = BINAURAL_CHANNELS;
3340 :
3341 708664 : Rmat[0][0] = 1.0f;
3342 708664 : Rmat[0][1] = 0.0f;
3343 708664 : Rmat[0][2] = 0.0f;
3344 :
3345 708664 : Rmat[1][0] = 0.0f;
3346 708664 : Rmat[1][1] = 1.0f;
3347 708664 : Rmat[1][2] = 0.0f;
3348 :
3349 708664 : Rmat[2][0] = 0.0f;
3350 708664 : Rmat[2][1] = 0.0f;
3351 708664 : Rmat[2][2] = 1.0f;
3352 :
3353 : /* CLDFB Analysis of input */
3354 3543320 : for ( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ )
3355 : {
3356 8503968 : for ( ch = 0; ch < numInChannels; ch++ )
3357 : {
3358 5669312 : if ( ch == 0 || nchan_transport == 2 )
3359 : {
3360 4251984 : cldfbAnalysis_ts(
3361 4251984 : &( output_f[ch][nBins * slot] ),
3362 4251984 : Cldfb_RealBuffer_in[ch][slot],
3363 4251984 : Cldfb_ImagBuffer_in[ch][slot],
3364 : nBins, hMasaExtRend->cldfbAnaRend[ch] );
3365 : }
3366 : else /* when nchan_transport == 1 and ch == 1 */
3367 : {
3368 : /* At mono input duplicate the channel to dual-mono, and apply gain
3369 : correction to ensure same overall level as in stereo mode */
3370 1417328 : v_multc( Cldfb_RealBuffer_in[0][slot], INV_SQRT_2, Cldfb_RealBuffer_in[0][slot], nBins );
3371 1417328 : v_multc( Cldfb_ImagBuffer_in[0][slot], INV_SQRT_2, Cldfb_ImagBuffer_in[0][slot], nBins );
3372 :
3373 1417328 : mvr2r( Cldfb_RealBuffer_in[0][slot], Cldfb_RealBuffer_in[1][slot], nBins );
3374 1417328 : mvr2r( Cldfb_ImagBuffer_in[0][slot], Cldfb_ImagBuffer_in[1][slot], nBins );
3375 : }
3376 : }
3377 : }
3378 :
3379 708664 : if ( hCombinedOrientationData )
3380 : {
3381 1011856 : for ( i = 0; i < 3; i++ )
3382 : {
3383 3035568 : for ( j = 0; j < 3; j++ )
3384 : {
3385 2276676 : Rmat[i][j] = hCombinedOrientationData->Rmat[hCombinedOrientationData->subframe_idx][i][j];
3386 : }
3387 : }
3388 :
3389 252964 : if ( nchan_transport == 2 )
3390 : {
3391 : /* in case of split rendering, determine the prototype rotation based on the main direction and use the same prototypes for the offset directions */
3392 126482 : adaptTransportSignalsHeadtracked( hCombinedOrientationData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat );
3393 :
3394 126482 : ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( hCombinedOrientationData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat );
3395 : }
3396 : }
3397 :
3398 :
3399 : /* Always using CLDFB decorrelation in MASA EXT renderer */
3400 708664 : max_band_decorr = hDiracDecBin->h_freq_domain_decorr_ap_params->max_band_decorr;
3401 :
3402 :
3403 708664 : ivas_dirac_dec_binaural_formulate_input_covariance_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, subframe,
3404 : subFrameTotalEne, IIReneLimiter );
3405 :
3406 708664 : ivas_dirac_dec_binaural_formulate_target_covariance_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat, subframe,
3407 708664 : hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0,
3408 : subFrameTotalEne, IIReneLimiter, NULL );
3409 :
3410 708664 : ivas_dirac_dec_binaural_determine_processing_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat, subframe,
3411 708664 : hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0,
3412 : 0, NULL );
3413 :
3414 708664 : pMultiBinPoseData = NULL;
3415 708664 : if ( hSplitRendWrapper != NULL )
3416 : {
3417 57664 : pMultiBinPoseData = &( hSplitRendWrapper->multiBinPoseData );
3418 :
3419 57664 : ivas_dirac_dec_binaural_process_output( hDiracDecBin, hSpatParamRendCom, hMasaExtRend->cldfbSynRend, output_f, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in,
3420 57664 : max_band_decorr, numInChannels, config_data.processReverb, subframe, tmp_Cldfb_out_re, tmp_Cldfb_out_im,
3421 : reverbRe, reverbIm, decorrRe, decorrIm, 1 );
3422 :
3423 172992 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
3424 : {
3425 576640 : for ( i = 0; i < CLDFB_SLOTS_PER_SUBFRAME; i++ )
3426 : {
3427 461312 : mvr2r( tmp_Cldfb_out_re[ch][i], Cldfb_Out_Real[ch][subframe * CLDFB_SLOTS_PER_SUBFRAME + i], CLDFB_NO_CHANNELS_MAX );
3428 461312 : mvr2r( tmp_Cldfb_out_im[ch][i], Cldfb_Out_Imag[ch][subframe * CLDFB_SLOTS_PER_SUBFRAME + i], CLDFB_NO_CHANNELS_MAX );
3429 : }
3430 : }
3431 : }
3432 : else
3433 : {
3434 651000 : ivas_dirac_dec_binaural_process_output( hDiracDecBin, hSpatParamRendCom, hMasaExtRend->cldfbSynRend, output_f, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in,
3435 651000 : max_band_decorr, numInChannels, config_data.processReverb, subframe, NULL, NULL,
3436 : reverbRe, reverbIm, decorrRe, decorrIm, 1 );
3437 : }
3438 :
3439 708664 : hDiracDecBin->hDiffuseDist = NULL;
3440 :
3441 708664 : if ( pMultiBinPoseData != NULL && pMultiBinPoseData->num_poses > 1 )
3442 : {
3443 : /* quaternion-based rotation from ivas_binRenderer_internal.c:ivas_binRenderer(), but using absolute rotation instead of delta rotations */
3444 : IVAS_QUATERNION Quaternions_rot, Quaternions_abs, *Quaternions_ref;
3445 : float Rmat_local[3][3];
3446 :
3447 40704 : if ( hCombinedOrientationData )
3448 : {
3449 40704 : Quaternions_ref = &hCombinedOrientationData->Quaternions[0];
3450 40704 : Quaternions_rot.w = -3.0f; /* signal to use Euler */
3451 40704 : Quaternions_abs.w = -3.0f; /* signal to use Euler */
3452 40704 : Quat2EulerDegree( *Quaternions_ref, &Quaternions_abs.z, &Quaternions_abs.y, &Quaternions_abs.x ); /*order in Quat2Euler seems to be reversed ?*/
3453 :
3454 217088 : for ( pos_idx = 1; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ )
3455 : {
3456 176384 : Quaternions_rot.x = Quaternions_abs.x + pMultiBinPoseData->relative_head_poses[pos_idx][0];
3457 176384 : Quaternions_rot.y = Quaternions_abs.y + pMultiBinPoseData->relative_head_poses[pos_idx][1];
3458 176384 : Quaternions_rot.z = Quaternions_abs.z + pMultiBinPoseData->relative_head_poses[pos_idx][2];
3459 :
3460 176384 : QuatToRotMat( Quaternions_rot, Rmat_local );
3461 :
3462 176384 : hDiracDecBin = hMasaExtRend->hDiracDecBin[pos_idx];
3463 176384 : assert( hDiracDecBin != NULL && "No DiracDecBin handle for this position" );
3464 :
3465 : /* re-use input covariance for the side renderings */
3466 529152 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
3467 : {
3468 352768 : mvr2r( hMasaExtRend->hDiracDecBin[0]->ChEne[ch], hDiracDecBin->ChEne[ch], hSpatParamRendCom->num_freq_bands );
3469 : }
3470 176384 : mvr2r( hMasaExtRend->hDiracDecBin[0]->ChCrossRe, hDiracDecBin->ChCrossRe, hSpatParamRendCom->num_freq_bands );
3471 176384 : mvr2r( hMasaExtRend->hDiracDecBin[0]->ChCrossIm, hDiracDecBin->ChCrossIm, hSpatParamRendCom->num_freq_bands );
3472 :
3473 176384 : ivas_dirac_dec_binaural_formulate_target_covariance_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat_local, subframe,
3474 176384 : hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0,
3475 : subFrameTotalEne, IIReneLimiter, NULL );
3476 :
3477 176384 : ivas_dirac_dec_binaural_determine_processing_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat_local, subframe,
3478 176384 : hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0,
3479 : 0, NULL );
3480 :
3481 : /* re-use reverb and decorr from main direction for the sides */
3482 176384 : ivas_dirac_dec_binaural_process_output( hDiracDecBin, hSpatParamRendCom, hMasaExtRend->cldfbSynRend, output_f, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in,
3483 176384 : max_band_decorr, numInChannels, config_data.processReverb, subframe, tmp_Cldfb_out_re, tmp_Cldfb_out_im,
3484 : reverbRe, reverbIm, decorrRe, decorrIm, 0 );
3485 :
3486 : /* copy from temporary buffer to the main split rendering buffer */
3487 529152 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
3488 : {
3489 1763840 : for ( i = 0; i < CLDFB_SLOTS_PER_SUBFRAME; i++ )
3490 : {
3491 1411072 : 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 );
3492 1411072 : 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 );
3493 : }
3494 : }
3495 :
3496 176384 : hDiracDecBin->hDiffuseDist = NULL;
3497 : }
3498 : }
3499 : }
3500 :
3501 : /* update this counter only after the last rendering of split directions */
3502 708664 : hSpatParamRendCom->slots_rendered += hSpatParamRendCom->subframe_nbslots[subframe];
3503 708664 : hSpatParamRendCom->subframes_rendered++;
3504 :
3505 708664 : return;
3506 : }
3507 :
3508 :
3509 420616 : void ivas_masa_ext_rend_parambin_render(
3510 : MASA_EXT_REND_HANDLE hMasaExtRend, /* i/o: MASA ext rend structure */
3511 : COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i : combined orientation handle */
3512 : float *output_f[], /* i/o: synthesized core-coder transport channels/DirAC output */
3513 : const int16_t num_subframes, /* i : number of subframes to render */
3514 : const SPLIT_REND_WRAPPER *hSplitRendWrapper, /* i : split rendering orientation data */
3515 : float Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : rendered orientations for split rend. real part of cldfb */
3516 : float Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] /* o : rendered orientations for split rend. imag part of cldfb */
3517 : )
3518 : {
3519 : int16_t subframe;
3520 : SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom;
3521 : float *p_output[BINAURAL_CHANNELS];
3522 : int16_t ch;
3523 :
3524 420616 : hSpatParamRendCom = hMasaExtRend->hSpatParamRendCom;
3525 :
3526 1261848 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
3527 : {
3528 841232 : p_output[ch] = output_f[ch];
3529 : }
3530 :
3531 420616 : hSpatParamRendCom->subframes_rendered = hSpatParamRendCom->dirac_read_idx;
3532 :
3533 1129280 : for ( subframe = 0; subframe < num_subframes; subframe++ )
3534 : {
3535 708664 : int16_t n_samples_sf = hSpatParamRendCom->slot_size * CLDFB_SLOTS_PER_SUBFRAME;
3536 708664 : hSpatParamRendCom->slots_rendered = 0;
3537 :
3538 708664 : ivas_masa_ext_rend_parambin_internal( hMasaExtRend, hCombinedOrientationData, p_output, hSpatParamRendCom->dirac_read_idx, hSplitRendWrapper, Cldfb_Out_Real, Cldfb_Out_Imag );
3539 :
3540 2125992 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
3541 : {
3542 1417328 : p_output[ch] += n_samples_sf;
3543 : }
3544 :
3545 708664 : ivas_combined_orientation_update_index( hCombinedOrientationData, n_samples_sf );
3546 :
3547 708664 : hSpatParamRendCom->dirac_read_idx = ( hSpatParamRendCom->dirac_read_idx + 1 ) % hSpatParamRendCom->dirac_md_buffer_length;
3548 : }
3549 :
3550 420616 : return;
3551 : }
|