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