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