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