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