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_fx.h"
38 : #include "ivas_prot_rend_fx.h"
39 : #include "ivas_cnst.h"
40 : #include "ivas_rom_binauralRenderer.h"
41 : #include "ivas_rom_binaural_crend_head.h"
42 : #include "ivas_rom_rend.h"
43 : #include "ivas_rom_com.h"
44 : #include "ivas_prot_fx.h"
45 :
46 : #include "wmc_auto.h"
47 :
48 : Word16 slot_fx[4] = { 32767, 16384, 10922, 8192 };
49 :
50 : /*-------------------------------------------------------------------------
51 : * Local constants
52 : *------------------------------------------------------------------------*/
53 :
54 : #define CLDFB_HALF_BIN_FREQUENCY_OFFSET 0.5f
55 : #define IVAS_TDET_DUCK_MULT_FAC_PARA_BIN ( 2.0f )
56 : #define IVAS_TDET_DUCK_MULT_FAC_PARA_BIN_LOW_BR ( 3.0f )
57 : #define SBA_CARDI_TARGET_ENERGY_GAIN 0.5f
58 :
59 : #define STEREO_PREPROCESS_IIR_FACTOR ( 0.9f )
60 : #define STEREO_PREPROCESS_IIR_FACTOR_Q15 ( 29491 )
61 : /* powf(0.95f, 4.0f) for sub-frame smoothing instead of CLDFB slot */
62 : #define ADAPT_HTPROTO_IIR_FAC 0.81450625f
63 :
64 : #define ADAPT_HTPROTO_ILD_LIM_DB0 1.0f
65 : #define ADAPT_HTPROTO_ILD_LIM_DB1 4.0f
66 : #define ADAPT_HTPROTO_ROT_LIM_0 0.4f
67 : #define ADAPT_HTPROTO_ROT_LIM_0_FX 429496736 // Q30
68 : #define TWO_POINT_FIVE_IN_Q13 20480 // Q13
69 : #define ADAPT_HTPROTO_IIR_FAC_FX 26689 // Q15
70 : #define LOG_10_BASE_2_Q29 1783446528 // Q29
71 : #define TAN_30_FX 17157 // Q15
72 : #define INV_TAN30_FX 28377 // Q14
73 : #define EPSILON_MANT 1180591621 /* 1e-12 = 0.5497558*(2^-39) in Q70 */
74 : #define EPSILON_EXP ( -39 )
75 : #define ONE_DIV_EPSILON_MANT 1953125000 /* 1e+12 = 0.9094947*(2^40) */
76 : #define ONE_DIV_EPSILON_EXP ( 40 )
77 : #define ADAPT_HTPROTO_ROT_LIM_1 0.8f
78 :
79 : #define MAX_GAIN_CACHE_SIZE ( ( MASA_MAXIMUM_DIRECTIONS * 3 ) + MAX_NUM_OBJECTS ) /* == different calls to get gains */
80 :
81 : typedef struct hrtfGainCache
82 : {
83 : Word16 azi;
84 : Word16 ele;
85 :
86 : Word32 shVec_fx[HRTF_SH_CHANNELS];
87 :
88 : } PARAMBIN_HRTF_GAIN_CACHE;
89 :
90 : typedef struct parambin_rend_config_data
91 : {
92 : Word16 separateCenterChannelRendering;
93 : IVAS_FORMAT ivas_format;
94 : MC_MODE mc_mode;
95 : Word32 ivas_total_brate;
96 : Word16 nchan_transport;
97 : Word32 qualityBasedSmFactor_fx; /* Q31 */
98 : Word16 processReverb;
99 : ISM_MODE ism_mode;
100 : } PARAMBIN_REND_CONFIG, *PARAMBIN_REND_CONFIG_HANDLE;
101 :
102 :
103 : /*-------------------------------------------------------------------------
104 : * Local function prototypes
105 : *------------------------------------------------------------------------*/
106 :
107 : static void ivas_dirac_dec_binaural_internal_fx( Decoder_Struct *st_ivas, COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, Word32 *output_f[] /*Q11*/, const Word16 nchan_transport, const Word16 subframe );
108 :
109 : static void ivas_dirac_dec_decorrelate_slot_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, const Word16 num_freq_bands, const Word16 slot, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME] /*q_inp*/[CLDFB_NO_CHANNELS_MAX], Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, Word16 q_inp, Word32 decRe[][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, Word32 decIm[] /*q_inp*/[CLDFB_NO_CHANNELS_MAX] );
110 :
111 : static void ivas_dirac_dec_binaural_formulate_input_covariance_matrices_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, PARAMBIN_REND_CONFIG_HANDLE hConfig, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const Word16 subframe, Word32 *subFrameTotalEne, Word16 *subFrameTotalEne_e, Word32 *IIReneLimiter, Word16 q );
112 :
113 : static void ivas_dirac_dec_binaural_formulate_target_covariance_matrices_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, const SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, const PARAMBIN_REND_CONFIG_HANDLE hConfig, Word32 Rmat[3][3], const Word16 subframe, const Word16 isHeadtracked, const Word32 *subFrameTotalEne, Word16 *subFrameTotalEne_e, const Word32 *IIReneLimiter, const MASA_ISM_DATA_HANDLE hMasaIsmData );
114 :
115 : static void ivas_dirac_dec_binaural_determine_processing_matrices_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, PARAMBIN_REND_CONFIG_HANDLE hConfig, const Word16 max_band_decorr, Word32 Rmat[3][3] /*Q30*/, const Word16 subframe, const Word16 isHeadtracked, const Word16 nchanSeparateChannels, const MASA_ISM_DATA_HANDLE hMasaIsmData );
116 :
117 : static void ivas_dirac_dec_binaural_process_output_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, HANDLE_CLDFB_FILTER_BANK cldfbSynDec[MAX_OUTPUT_CHANNELS], Word32 *output_fx[] /*q_out*/, Word16 *q_out, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, const Word16 q_inp, const Word16 max_band_decorr, const Word16 numInChannels, const Word16 processReverb, const Word16 subframe, const Word16 q_mat, Word32 outRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 outIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 reverbRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 reverbIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 decorrRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 decorrIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word16 *Q_inp_mix, const Word8 recompute );
118 :
119 : static void adaptTransportSignalsHeadtracked_fx( COMBINED_ORIENTATION_HANDLE hHeadTrackData, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, Word16 q_inp, const Word16 nBins, const Word16 nSlots, Word32 Rmat[3][3] /*Q30*/ );
120 :
121 : static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked_fx( COMBINED_ORIENTATION_HANDLE hHeadTrackData, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const Word16 nBins, const Word16 nSlots, Word32 Rmat[3][3] /*Q30*/ );
122 :
123 : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
124 : static void hrtfShGetHrtf_fx( const Word16 bin, const Word16 aziDeg, const Word16 eleDeg, Word32 *lRealp, Word32 *lImagp, Word32 *rRealp, Word32 *rImagp, PARAMBIN_HRTF_GAIN_CACHE *gainCache, const Word16 useCachedValue, HRTFS_PARAMBIN_HANDLE hHrtfParambin );
125 : #else
126 : static void hrtfShGetHrtf_fx( const Word16 bin, const Word16 aziDeg, const Word16 eleDeg, Word32 *lRealp, Word32 *lImagp, Word32 *rRealp, Word32 *rImagp, PARAMBIN_HRTF_GAIN_CACHE *gainCache, const Word16 useCachedValue );
127 : #endif
128 :
129 : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
130 : static void getDirectPartGains_fx( const Word16 bin, Word16 aziDeg, Word16 eleDeg, Word32 *lRealp, Word32 *lImagp, Word32 *rRealp, Word32 *rImagp, const UWord8 renderStereoOutputInsteadOfBinaural, Word32 Rmat[3][3] /*Q30*/, PARAMBIN_HRTF_GAIN_CACHE *gainCache, const Word16 isHeadtracked, HRTFS_PARAMBIN_HANDLE hHrtfParambin );
131 : #else
132 : static void getDirectPartGains_fx( const Word16 bin, Word16 aziDeg, Word16 eleDeg, Word32 *lRealp, Word32 *lImagp, Word32 *rRealp, Word32 *rImagp, const UWord8 renderStereoOutputInsteadOfBinaural, Word32 Rmat[3][3] /*Q30*/, PARAMBIN_HRTF_GAIN_CACHE *gainCache, const Word16 isHeadtracked );
133 : #endif
134 :
135 : static void ivas_masa_ext_rend_parambin_internal_fx( MASA_EXT_REND_HANDLE hMasaExtRend, COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, Word32 *output_fx[] /*Q11*/, const Word16 subframe, const SPLIT_REND_WRAPPER *hSplitRendWrapper, Word32 Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], Word32 Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] );
136 :
137 : static void formulate2x2MixingMatrix_fx( Word32 Ein1_fx /*q_Ein*/, Word32 Ein2_fx /*q_Ein*/, Word16 q_Ein, Word32 CinRe_fx /*q_Cin*/, Word32 CinIm_fx /*q_Cin*/, Word16 q_Cin, Word32 Eout1_fx /*q_Eout*/, Word32 Eout2_fx /*q_Eout*/, Word16 q_Eout, Word32 CoutRe_fx /*q_Cout*/, Word32 CoutIm_fx /*q_Cout*/, Word16 q_Cout, Word32 Q_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*Q31*/, Word32 Mre_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_M*/, Word32 Mim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_M*/, Word16 *q_M, const Word16 regularizationFactor_fx /*Q14*/ );
138 :
139 : static void matrixMul_fx( Word32 Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_A*/, Word32 Aim[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_A*/, Word16 *q_A, Word32 Bre[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_B*/, Word32 Bim[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_B*/, Word16 *q_B, Word32 outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_out*/, Word32 outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_out*/, Word16 *q_out );
140 :
141 : static void matrixTransp2Mul_fx(
142 : Word32 Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_A*/,
143 : Word32 Aim[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_A*/,
144 : Word16 *q_A,
145 : Word32 Bre[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_B*/,
146 : Word32 Bim[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_B*/,
147 : Word16 *q_B,
148 : Word32 Ascale,
149 : Word32 Bscale,
150 : Word32 outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_out*/,
151 : Word32 outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_out*/,
152 : Word16 *q_out );
153 :
154 :
155 : /*-------------------------------------------------------------------------
156 : * ivas_dirac_dec_init_binaural_data()
157 : *
158 : * Initialize parametric binaural renderer
159 : *------------------------------------------------------------------------*/
160 :
161 462 : ivas_error ivas_dirac_dec_init_binaural_data_fx(
162 : Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
163 : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
164 : HRTFS_PARAMBIN_HANDLE *phHrtfParambin /* i : HRTF structure for rendering */
165 : #else
166 : HRTFS_PARAMBIN_HANDLE hHrtfParambin /* i : HRTF structure for rendering */
167 : #endif
168 : )
169 : {
170 : DIRAC_DEC_BIN_HANDLE hDiracDecBin;
171 : Word16 nBins;
172 : Word32 output_Fs;
173 : RENDERER_TYPE renderer_type;
174 : Word16 j, k, bin;
175 : Word32 binCenterFreq_fx;
176 : Word16 tmpFloat_fx;
177 : Word16 tmp;
178 : Word16 tmp_e;
179 : Word16 tmp2;
180 : ivas_error error;
181 :
182 : Word16 num_poses, pos_idx;
183 : #ifdef FIX_587_DEFAULT_REVERB
184 : const IVAS_ROOM_ACOUSTICS_CONFIG_DATA *pRoomAcoustics;
185 : #endif
186 :
187 462 : num_poses = 1;
188 462 : IF( st_ivas->hSplitBinRend != NULL )
189 : {
190 0 : num_poses = st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses;
191 0 : move16();
192 : }
193 :
194 924 : FOR( pos_idx = 0; pos_idx < num_poses; pos_idx++ )
195 : {
196 462 : hDiracDecBin = st_ivas->hDiracDecBin[pos_idx];
197 462 : move32();
198 :
199 462 : IF( hDiracDecBin == NULL )
200 : {
201 462 : IF( ( hDiracDecBin = (DIRAC_DEC_BIN_HANDLE) malloc( sizeof( DIRAC_DEC_BIN_DATA ) ) ) == NULL )
202 : {
203 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC binaural handle " );
204 : }
205 :
206 462 : hDiracDecBin->hTdDecorr = NULL;
207 462 : hDiracDecBin->hReverb = NULL;
208 462 : hDiracDecBin->h_freq_domain_decorr_ap_params = NULL;
209 462 : hDiracDecBin->h_freq_domain_decorr_ap_state = NULL;
210 : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
211 462 : hDiracDecBin->phHrtfParambin = NULL;
212 : #endif
213 : }
214 :
215 462 : output_Fs = st_ivas->hDecoderConfig->output_Fs;
216 462 : move32();
217 462 : nBins = st_ivas->hSpatParamRendCom->num_freq_bands;
218 462 : move16();
219 462 : renderer_type = st_ivas->renderer_type;
220 462 : move32();
221 :
222 1386 : FOR( j = 0; j < BINAURAL_CHANNELS; j++ )
223 : {
224 6468 : FOR( k = 0; k < BINAURAL_CHANNELS + MAX_NUM_OBJECTS; k++ )
225 : {
226 5544 : set16_fx( hDiracDecBin->processMtxRe_fx[j][k], 0, nBins );
227 5544 : set16_fx( hDiracDecBin->processMtxIm_fx[j][k], 0, nBins );
228 5544 : set16_fx( hDiracDecBin->processMtxRePrev_fx[j][k], 0, nBins );
229 5544 : set16_fx( hDiracDecBin->processMtxImPrev_fx[j][k], 0, nBins );
230 : }
231 :
232 2772 : FOR( k = 0; k < BINAURAL_CHANNELS; k++ )
233 : {
234 1848 : set16_fx( hDiracDecBin->processMtxDecRe_fx[j][k], 0, nBins );
235 1848 : set16_fx( hDiracDecBin->processMtxDecIm_fx[j][k], 0, nBins );
236 : }
237 924 : set32_fx( hDiracDecBin->ChEnePrev_fx[j], 0, nBins );
238 924 : set32_fx( hDiracDecBin->ChEneOutPrev_fx[j], 0, nBins );
239 924 : set16_fx( hDiracDecBin->ChEnePrev_e[j], 0, nBins );
240 924 : set16_fx( hDiracDecBin->ChEneOutPrev_e[j], 0, nBins );
241 : }
242 462 : set32_fx( hDiracDecBin->ChCrossRePrev_fx, 0, nBins );
243 462 : set32_fx( hDiracDecBin->ChCrossImPrev_fx, 0, nBins );
244 462 : set16_fx( hDiracDecBin->ChCrossRePrev_e, 0, nBins );
245 462 : set16_fx( hDiracDecBin->ChCrossImPrev_e, 0, nBins );
246 462 : set32_fx( hDiracDecBin->ChCrossReOutPrev_fx, 0, nBins );
247 462 : set32_fx( hDiracDecBin->ChCrossImOutPrev_fx, 0, nBins );
248 462 : set16_fx( hDiracDecBin->ChCrossReOutPrev_e, 0, nBins );
249 462 : set16_fx( hDiracDecBin->ChCrossImOutPrev_e, 0, nBins );
250 462 : hDiracDecBin->renderStereoOutputInsteadOfBinaural = 0;
251 462 : move16();
252 :
253 462 : hDiracDecBin->q_processMtx = Q15;
254 462 : hDiracDecBin->q_processMtxSCCR = Q15;
255 462 : hDiracDecBin->q_processMtxPrev = Q15;
256 462 : hDiracDecBin->q_processMtxPrevSCCR = Q15;
257 462 : hDiracDecBin->q_processMtxDec = Q15;
258 462 : hDiracDecBin->q_processMtxDecPrev = Q15;
259 462 : move16();
260 462 : move16();
261 462 : move16();
262 462 : move16();
263 462 : move16();
264 462 : move16();
265 :
266 22222 : FOR( bin = 0; bin < nBins; bin++ )
267 : {
268 21760 : binCenterFreq_fx = L_mult0( extract_l( L_shr( output_Fs, 1 ) ), div_s( add( shl( bin, 1 ), 1 ), shl( nBins, 1 ) ) ) /*( (float) bin + 0.5f ) / (float) nBins * ( (float) output_Fs / 2.0f )*/; /*Q15*/
269 : /* These formulas and values are from Christian Borss's publication for binaural diffuse field coherence */
270 21760 : tmp = BASOP_Util_Divide3232_Scale( binCenterFreq_fx, 2700 << Q15, &tmp_e );
271 21760 : IF( tmp_e < 0 )
272 : {
273 1386 : tmp = shl( tmp, tmp_e ); /*q15*/
274 1386 : tmp_e = 0;
275 1386 : move16();
276 : }
277 21760 : tmpFloat_fx = s_max( 0, sub( shl_sat( 1, sub( 15, tmp_e ) ), tmp ) ) /*max( 0.0f, 1.0f - binCenterFreq / 2700.0f )*/; /*Q15-tmp_e*/
278 21760 : tmp2 = extract_l( Mult_32_32( binCenterFreq_fx, 1952258 /*=2^31*180/(550)/360*/ ) % 32767 ); /* Q15 */ //*binCenterFreq_fx * EVS_PI / 550.0f*/
279 21760 : hDiracDecBin->diffuseFieldCoherence_fx[bin] = L_shl( L_mult0( divide3232( tmpFloat_fx, Mult_32_16( binCenterFreq_fx, 187 /*2^15*pi/550*/ ) ), getSineWord16R2( tmp2 ) ), tmp_e ); /*tmpFloat * sinf( binCenterFreq * EVS_PI / 550.0f ) / ( binCenterFreq * EVS_PI / 550.0f );*/ /* Q30 */
280 21760 : hDiracDecBin->diffuseFieldCoherence_fx[bin] = L_shl( hDiracDecBin->diffuseFieldCoherence_fx[bin], 1 ); /* Q31 */
281 21760 : move32();
282 21760 : move32();
283 : }
284 :
285 4620 : FOR( bin = 0; bin < BINAURAL_COHERENCE_DIFFERENCE_BINS; bin++ )
286 : {
287 4158 : hDiracDecBin->diffuseFieldCoherenceX_fx[bin] = L_add( hDiracDecBin->diffuseFieldCoherence_fx[bin], diffuseFieldCoherenceDifferenceX_fx[bin] );
288 4158 : hDiracDecBin->diffuseFieldCoherenceY_fx[bin] = L_add( hDiracDecBin->diffuseFieldCoherence_fx[bin], diffuseFieldCoherenceDifferenceY_fx[bin] );
289 4158 : hDiracDecBin->diffuseFieldCoherenceZ_fx[bin] = L_add( hDiracDecBin->diffuseFieldCoherence_fx[bin], diffuseFieldCoherenceDifferenceZ_fx[bin] );
290 4158 : move32();
291 4158 : move32();
292 4158 : move32();
293 : }
294 :
295 462 : IF( EQ_32( renderer_type, RENDERER_BINAURAL_PARAMETRIC ) ) /* Indication of binaural rendering without room effect */
296 : {
297 173 : set32_fx( hDiracDecBin->earlyPartEneCorrection_fx, ONE_IN_Q28, CLDFB_NO_CHANNELS_MAX );
298 173 : hDiracDecBin->q_earlyPartEneCorrection = Q28;
299 173 : move16();
300 173 : hDiracDecBin->hReverb = NULL;
301 : }
302 289 : ELSE IF( EQ_32( renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) /* Indication of binaural rendering with room effect */
303 : {
304 : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
305 : #ifdef NONBE_FIX_981_PARAMBIN_DEFAULT_EARLY_PART
306 278 : IF( EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) )
307 : {
308 163 : Copy32( ( *phHrtfParambin )->parametricEarlyPartEneCorrection_fx, hDiracDecBin->earlyPartEneCorrection_fx, nBins );
309 : #ifdef FIX_587_DEFAULT_REVERB
310 163 : pRoomAcoustics = NULL;
311 : #endif
312 : }
313 : ELSE
314 : {
315 115 : set32_fx( hDiracDecBin->earlyPartEneCorrection_fx, ONE_IN_Q28, CLDFB_NO_CHANNELS_MAX );
316 : #ifdef FIX_587_DEFAULT_REVERB
317 115 : pRoomAcoustics = &( st_ivas->hRenderConfig->roomAcoustics );
318 : #endif
319 : }
320 : #else
321 : Copy32( ( *phHrtfParambin )->parametricEarlyPartEneCorrection_fx, hDiracDecBin->earlyPartEneCorrection_fx, nBins );
322 : #endif
323 : #else
324 : Copy32( hHrtfParambin->parametricEarlyPartEneCorrection_fx, hDiracDecBin->earlyPartEneCorrection_fx, nBins );
325 : #endif
326 278 : hDiracDecBin->q_earlyPartEneCorrection = Q28;
327 278 : move16();
328 : /* reconfiguration needed when Reverb. parameters are changed -> close and open the handle again */
329 278 : test();
330 278 : test();
331 278 : IF( hDiracDecBin->hReverb != NULL && ( ( NE_16( hDiracDecBin->hReverb->numBins, nBins ) ) ||
332 : ( NE_16( hDiracDecBin->hReverb->blockSize, CLDFB_SLOTS_PER_SUBFRAME ) ) ) )
333 : {
334 0 : ivas_binaural_reverb_close_fx( &( hDiracDecBin->hReverb ) );
335 : }
336 :
337 278 : IF( hDiracDecBin->hReverb == NULL && EQ_16( pos_idx, 0 ) ) /* open reverb only for the main direction */
338 : {
339 :
340 : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
341 : #ifdef FIX_587_DEFAULT_REVERB
342 : #ifdef FIX_1139_REV_COLORATION_SHORT_T60
343 278 : IF( NE_32( ( error = ivas_binaural_reverb_init( &hDiracDecBin->hReverb, st_ivas->hHrtfStatistics, nBins, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, pRoomAcoustics, output_Fs, ( *phHrtfParambin )->parametricReverberationTimes_fx, ( *phHrtfParambin )->parametricReverberationEneCorrections_fx, hDiracDecBin->earlyPartEneCorrection_fx ) ), IVAS_ERR_OK ) )
344 : #else
345 : if ( NE_32( ( error = ivas_binaural_reverb_init( &hDiracDecBin->hReverb, st_ivas->hHrtfStatistics, nBins, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, pRoomAcoustics, output_Fs, ( *phHrtfParambin )->parametricReverberationTimes_fx, ( *phHrtfParambin )->parametricReverberationEneCorrections_fx ) ), IVAS_ERR_OK ) )
346 : #endif
347 : #else
348 : if ( NE_32( ( error = ivas_binaural_reverb_init( &hDiracDecBin->hReverb, st_ivas->hHrtfStatistics, nBins, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, &( st_ivas->hRenderConfig->roomAcoustics ), output_Fs, ( *phHrtfParambin )->parametricReverberationTimes_fx, ( *phHrtfParambin )->parametricReverberationEneCorrections_fx ) ), IVAS_ERR_OK ) )
349 : #endif
350 : #else
351 : if ( ( error = ivas_binaural_reverb_init( &hDiracDecBin->hReverb, st_ivas->hHrtfStatistics, nBins, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, &( st_ivas->hRenderConfig->roomAcoustics ), output_Fs, st_ivas->hHrtfParambin->parametricReverberationTimes_fx, st_ivas->hHrtfParambin->parametricReverberationEneCorrections_fx ) ) != IVAS_ERR_OK )
352 : #endif
353 : {
354 0 : return error;
355 : }
356 : }
357 : }
358 11 : ELSE IF( EQ_32( renderer_type, RENDERER_STEREO_PARAMETRIC ) )
359 : {
360 11 : set32_fx( hDiracDecBin->earlyPartEneCorrection_fx, ONE_IN_Q28, CLDFB_NO_CHANNELS_MAX );
361 11 : hDiracDecBin->q_earlyPartEneCorrection = Q28;
362 11 : hDiracDecBin->hReverb = NULL;
363 11 : hDiracDecBin->renderStereoOutputInsteadOfBinaural = 1;
364 11 : move16();
365 11 : move16();
366 : }
367 : ELSE /* Not valid renderer type for this renderer */
368 : {
369 0 : assert( false );
370 : }
371 :
372 462 : hDiracDecBin->hDiffuseDist = NULL; /* Memory is allocated from stack during runtime when needed */
373 :
374 462 : if ( hDiracDecBin->hTdDecorr == NULL )
375 : {
376 462 : hDiracDecBin->useTdDecorr = 0;
377 462 : move16();
378 : }
379 :
380 462 : IF( hDiracDecBin->h_freq_domain_decorr_ap_params != NULL )
381 : {
382 0 : ivas_dirac_dec_decorr_close_fx( &hDiracDecBin->h_freq_domain_decorr_ap_params, &hDiracDecBin->h_freq_domain_decorr_ap_state );
383 : }
384 :
385 462 : if ( pos_idx == 0 ) /* open decorrelator only for the main direction */
386 : {
387 462 : IF( NE_32( ( 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 ) )
388 : {
389 0 : return error;
390 : }
391 :
392 462 : test();
393 462 : test();
394 462 : IF( !hDiracDecBin->useTdDecorr && !( EQ_32( st_ivas->ivas_format, ISM_FORMAT ) && EQ_32( st_ivas->ism_mode, ISM_MODE_PARAM ) ) )
395 : {
396 : Word16 frequency_axis_fx[CLDFB_NO_CHANNELS_MAX];
397 111 : ivas_dirac_dec_get_frequency_axis_fx( frequency_axis_fx, output_Fs, nBins );
398 :
399 111 : IF( NE_32( ( error = ivas_dirac_dec_decorr_open_fx( &( hDiracDecBin->h_freq_domain_decorr_ap_params ),
400 : &( hDiracDecBin->h_freq_domain_decorr_ap_state ),
401 : nBins,
402 : BINAURAL_CHANNELS,
403 : BINAURAL_CHANNELS,
404 : DIRAC_SYNTHESIS_PSD_LS,
405 : frequency_axis_fx,
406 : BINAURAL_CHANNELS,
407 : output_Fs ) ),
408 : IVAS_ERR_OK ) )
409 : {
410 0 : return error;
411 : }
412 : }
413 : }
414 : else
415 : {
416 0 : hDiracDecBin->useTdDecorr = st_ivas->hDiracDecBin[0]->useTdDecorr; /* copy the flag, but the implementation re-uses the decorrelated signal */
417 : }
418 :
419 462 : hDiracDecBin->reqularizationFactor_fx = configure_reqularization_factor_fx( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate ); /* Q14 */
420 462 : move16();
421 :
422 : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
423 462 : hDiracDecBin->phHrtfParambin = phHrtfParambin;
424 : #endif
425 :
426 462 : st_ivas->hDiracDecBin[pos_idx] = hDiracDecBin;
427 : }
428 :
429 : /* allocate transport channels */
430 462 : IF( st_ivas->hTcBuffer == NULL )
431 : {
432 : Word16 nchan_to_allocate;
433 : Word16 n_samples_granularity;
434 :
435 65 : nchan_to_allocate = 2 * BINAURAL_CHANNELS;
436 65 : move16();
437 65 : if ( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) )
438 : {
439 : #ifdef FIX_1222_OMASA_DEC_CHANNEL_BUFFERS
440 15 : nchan_to_allocate = add( BINAURAL_CHANNELS, st_ivas->nchan_ism );
441 : #else
442 : nchan_to_allocate = 2 * BINAURAL_CHANNELS + 2;
443 : move16();
444 : #endif
445 : }
446 :
447 65 : n_samples_granularity = NS2SA_FX2( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS );
448 65 : test();
449 65 : test();
450 65 : IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) && EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) && EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) )
451 : {
452 1 : n_samples_granularity = NS2SA_FX2( st_ivas->hDecoderConfig->output_Fs, FRAME_SIZE_NS / MAX_PARAM_SPATIAL_SUBFRAMES ); /* Use the same granularity as tdrend */
453 : }
454 :
455 65 : IF( NE_32( ( error = ivas_jbm_dec_tc_buffer_open_fx( st_ivas, TC_BUFFER_MODE_RENDERER, ivas_jbm_dec_get_num_tc_channels_fx( st_ivas ), nchan_to_allocate, nchan_to_allocate, n_samples_granularity ) ), IVAS_ERR_OK ) )
456 : {
457 0 : return error;
458 : }
459 : }
460 462 : return IVAS_ERR_OK;
461 : }
462 :
463 : /*-------------------------------------------------------------------------
464 : * ivas_dirac_dec_close_binaural_data()
465 : *
466 : * Close parametric binaural renderer
467 : *------------------------------------------------------------------------*/
468 3167 : void ivas_dirac_dec_close_binaural_data(
469 : DIRAC_DEC_BIN_HANDLE *hBinaural /* i/o: decoder DirAC binaural data handle */
470 : )
471 : {
472 : int16_t pos_idx;
473 3167 : test();
474 3167 : IF( hBinaural == NULL || *hBinaural == NULL )
475 : {
476 2693 : return;
477 : }
478 :
479 4266 : FOR( pos_idx = 0; pos_idx < MAX_HEAD_ROT_POSES; pos_idx++ )
480 : {
481 3792 : IF( hBinaural[pos_idx] != NULL )
482 : {
483 474 : IF( hBinaural[pos_idx]->hReverb != NULL )
484 : {
485 278 : ivas_binaural_reverb_close_fx( &( hBinaural[pos_idx]->hReverb ) );
486 : }
487 :
488 474 : ivas_td_decorr_dec_close( &( hBinaural[pos_idx]->hTdDecorr ) );
489 :
490 474 : if ( hBinaural[pos_idx]->h_freq_domain_decorr_ap_params != NULL )
491 : {
492 128 : ivas_dirac_dec_decorr_close_fx( &( hBinaural[pos_idx]->h_freq_domain_decorr_ap_params ), &( hBinaural[pos_idx]->h_freq_domain_decorr_ap_state ) );
493 : }
494 :
495 474 : free( hBinaural[pos_idx] );
496 474 : hBinaural[pos_idx] = NULL;
497 : }
498 : }
499 :
500 474 : return;
501 : }
502 : /*-------------------------------------------------------------------------
503 : * ivas_dirac_dec_binaural_copy_hrtfs()
504 : *
505 : * Temporary function for copying HRTF data from rom tables if no binary
506 : * file was given.
507 : *------------------------------------------------------------------------*/
508 1628 : ivas_error ivas_dirac_dec_binaural_copy_hrtfs_fx(
509 : HRTFS_PARAMBIN_HANDLE *hHrtfParambin /* i/o: HRTF structure for rendering */
510 : )
511 : {
512 : Word16 i, j;
513 1628 : test();
514 1628 : IF( hHrtfParambin != NULL && *hHrtfParambin != NULL )
515 : {
516 : /* Tables already loaded from file */
517 1521 : return IVAS_ERR_OK;
518 : }
519 : ELSE
520 : {
521 : /* Initialise tables from ROM */
522 : HRTFS_PARAMBIN *hrtfParambin;
523 107 : IF( ( hrtfParambin = (HRTFS_PARAMBIN *) malloc( sizeof( HRTFS_PARAMBIN ) ) ) == NULL )
524 : {
525 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for parametric binauralizer HRTF tables" );
526 : }
527 321 : FOR( i = 0; i < BINAURAL_CHANNELS; i++ )
528 : {
529 3638 : FOR( j = 0; j < HRTF_SH_CHANNELS; j++ )
530 : {
531 3424 : Copy( hrtfShCoeffsRe_fx[i][j], hrtfParambin->hrtfShCoeffsRe_fx[i][j], HRTF_NUM_BINS ); /*Q14*/
532 3424 : Copy( hrtfShCoeffsIm_fx[i][j], hrtfParambin->hrtfShCoeffsIm_fx[i][j], HRTF_NUM_BINS ); /*Q14*/
533 : }
534 : }
535 107 : Copy32( parametricReverberationTimes_fx, hrtfParambin->parametricReverberationTimes_fx, CLDFB_NO_CHANNELS_MAX ); /*Q26*/
536 107 : Copy32( parametricReverberationEneCorrections_fx, hrtfParambin->parametricReverberationEneCorrections_fx, CLDFB_NO_CHANNELS_MAX ); /*Q31*/
537 107 : Copy32( parametricEarlyPartEneCorrection_fx, hrtfParambin->parametricEarlyPartEneCorrection_fx, CLDFB_NO_CHANNELS_MAX ); /*Q28*/
538 107 : *hHrtfParambin = hrtfParambin;
539 : }
540 :
541 107 : return IVAS_ERR_OK;
542 : }
543 :
544 :
545 : /*-------------------------------------------------------------------------
546 : * void ivas_dirac_dec_binaural_render_fx()
547 : *
548 : *
549 : *------------------------------------------------------------------------*/
550 72073 : void ivas_dirac_dec_binaural_render_fx(
551 : Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */
552 : const UWord16 nSamplesAsked, /* i : number of CLDFB slots requested */
553 : UWord16 *nSamplesRendered, /* o : number of CLDFB slots rendered */
554 : UWord16 *nSamplesAvailable, /* o : number of CLDFB slots still to render */
555 : const Word16 nchan_transport, /* i : number of transport channels */
556 : Word32 *output_f[] /* o : rendered time signal, Q11 */
557 : )
558 : {
559 : Word16 slots_to_render, first_sf, last_sf, subframe_idx;
560 : UWord16 slot_size, ch;
561 : UWord16 nchan_out;
562 : SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom;
563 : Word32 *output_fx_local[MAX_OUTPUT_CHANNELS];
564 : Word32 output_fx_local_buff[MAX_OUTPUT_CHANNELS][L_FRAME48k];
565 : Word16 output_length;
566 :
567 72073 : hSpatParamRendCom = st_ivas->hSpatParamRendCom;
568 72073 : nchan_out = BINAURAL_CHANNELS;
569 72073 : move16();
570 216219 : FOR( ch = 0; ch < nchan_out; ch++ )
571 : {
572 144146 : output_fx_local[ch] = output_fx_local_buff[ch];
573 : }
574 72073 : slot_size = NS2SA_FX2( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS );
575 :
576 : /* loop for synthesis, assume we always have to render in multiples of 5ms subframes with spills */
577 72073 : slots_to_render = s_min( sub( hSpatParamRendCom->num_slots, hSpatParamRendCom->slots_rendered ), idiv1616( (Word16) nSamplesAsked, (Word16) slot_size ) );
578 72073 : *nSamplesRendered = imult1616( slots_to_render, slot_size );
579 72073 : move16();
580 72073 : first_sf = hSpatParamRendCom->subframes_rendered;
581 72073 : last_sf = first_sf;
582 72073 : move16();
583 72073 : move16();
584 :
585 347398 : WHILE( slots_to_render > 0 )
586 : {
587 275325 : slots_to_render = sub( slots_to_render, hSpatParamRendCom->subframe_nbslots[last_sf] );
588 275325 : last_sf = add( last_sf, 1 );
589 : }
590 :
591 72073 : output_length = 0;
592 72073 : move16();
593 347398 : FOR( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ )
594 : {
595 275325 : Word16 n_samples_sf = imult1616( slot_size, hSpatParamRendCom->subframe_nbslots[subframe_idx] );
596 275325 : ivas_dirac_dec_binaural_internal_fx( st_ivas, st_ivas->hCombinedOrientationData, output_fx_local, nchan_transport, subframe_idx );
597 :
598 825975 : FOR( ch = 0; ch < nchan_out; ch++ )
599 : {
600 550650 : output_fx_local[ch] += n_samples_sf;
601 : }
602 :
603 275325 : output_length = add( output_length, n_samples_sf );
604 :
605 : /* update combined orientation access index */
606 275325 : ivas_combined_orientation_update_index( st_ivas->hCombinedOrientationData, n_samples_sf );
607 : }
608 :
609 216219 : FOR( ch = 0; ch < nchan_out; ch++ )
610 : {
611 144146 : Copy32( output_fx_local_buff[ch], output_f[ch], output_length );
612 : }
613 :
614 72073 : IF( EQ_16( hSpatParamRendCom->slots_rendered, hSpatParamRendCom->num_slots ) )
615 : {
616 68602 : hSpatParamRendCom->dirac_read_idx = add( hSpatParamRendCom->dirac_read_idx, DEFAULT_JBM_SUBFRAMES_5MS ) % hSpatParamRendCom->dirac_md_buffer_length;
617 68602 : move16();
618 : }
619 :
620 72073 : *nSamplesAvailable = imult1616( sub( hSpatParamRendCom->num_slots, hSpatParamRendCom->slots_rendered ), slot_size );
621 72073 : move16();
622 :
623 72073 : return;
624 : }
625 :
626 : /*-------------------------------------------------------------------------
627 : * ivas_dirac_dec_binaural_sba_gain()
628 : *
629 : * loudness correction for parametric binaural renderer
630 : *------------------------------------------------------------------------*/
631 45535 : void ivas_dirac_dec_binaural_sba_gain_fx(
632 : Word32 *output[], /* i/o: synthesized core-coder transport channels/DirAC output, inp Qx, out Qx-1 */
633 : const Word16 nchan_remapped, /* i : num channels after remapping of TCs */
634 : const Word16 output_frame /* i : output frame length */
635 : )
636 : {
637 : Word16 n;
638 : Word16 gain; /*Q-14*/
639 :
640 45535 : IF( EQ_16( nchan_remapped, 1 ) )
641 : {
642 16159 : gain = 23681; /*Q14*/
643 16159 : move16();
644 : }
645 : ELSE
646 : {
647 29376 : gain = 22376; /*Q14*/
648 29376 : move16();
649 : }
650 :
651 120446 : FOR( n = 0; n < nchan_remapped; n++ )
652 : {
653 74911 : v_multc_fixed_16( output[n], gain, output[n], output_frame ); /* Qx to Qx-1*/
654 : }
655 :
656 45535 : return;
657 : }
658 :
659 :
660 : /*-------------------------------------------------------------------------
661 : * Local functions
662 : *------------------------------------------------------------------------*/
663 275325 : static void ivas_dirac_dec_binaural_internal_fx(
664 : Decoder_Struct *st_ivas,
665 : COMBINED_ORIENTATION_HANDLE hCombinedOrientationData,
666 : Word32 *output_fx[], /*Q11*/
667 : const Word16 nchan_transport,
668 : const Word16 subframe )
669 : {
670 275325 : Word16 q_input = 11;
671 275325 : move16();
672 275325 : IF( st_ivas->hSCE[0] )
673 : {
674 161083 : Word16 shift = getScaleFactor32( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->cngNoiseLevel, FFTCLDFBLEN );
675 161083 : IF( LT_16( sub( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->cngNoiseLevelExp, shift ), 4 ) )
676 : {
677 11702 : shift = sub( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->cngNoiseLevelExp, 4 );
678 : }
679 161083 : scale_sig32( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->cngNoiseLevel, FFTCLDFBLEN, shift );
680 161083 : st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->cngNoiseLevelExp = sub( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->cngNoiseLevelExp, shift );
681 161083 : move16();
682 : }
683 : Word16 q_cldfb[6][CLDFB_SLOTS_PER_SUBFRAME];
684 1927275 : FOR( Word16 ind = 0; ind < 6; ind++ )
685 : {
686 8259750 : FOR( Word16 ind2 = 0; ind2 < 4; ind2++ )
687 : {
688 6607800 : q_cldfb[ind][ind2] = q_input;
689 6607800 : move16();
690 : }
691 : }
692 275325 : Word16 q_cldfb_temp = sub( q_input, 1 );
693 : DIRAC_DEC_BIN_HANDLE hDiracDecBin;
694 : SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom;
695 : PARAMBIN_REND_CONFIG config_data;
696 : Word16 slot, ch, numInChannels;
697 : Word32 Cldfb_RealBuffer_in_fx[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
698 : Word32 Cldfb_ImagBuffer_in_fx[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
699 : Word16 nchanSeparateChannels;
700 : Word32 Rmat_fx[3][3];
701 : Word16 max_band_decorr;
702 : DIFFUSE_DISTRIBUTION_DATA diffuseDistData;
703 : Word16 nBins, offsetSamples;
704 : Word16 i, j;
705 : Word16 q_mat, q_out;
706 : Word16 pos_idx;
707 : MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData;
708 : Word32 tmp_Cldfb_out_re[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
709 : Word32 tmp_Cldfb_out_im[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
710 : /* 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 */
711 : Word32 reverbRe_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
712 : Word32 reverbIm_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
713 : Word32 decorrRe_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
714 : Word32 decorrIm_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
715 : Word32 subFrameTotalEne_fx[CLDFB_NO_CHANNELS_MAX];
716 : Word16 subFrameTotalEne_e[CLDFB_NO_CHANNELS_MAX];
717 : Word32 IIReneLimiter_fx[CLDFB_NO_CHANNELS_MAX];
718 : Word16 Q_inp_mix;
719 :
720 275325 : hDiracDecBin = st_ivas->hDiracDecBin[0];
721 275325 : assert( hDiracDecBin );
722 275325 : hSpatParamRendCom = st_ivas->hSpatParamRendCom;
723 275325 : nBins = hSpatParamRendCom->num_freq_bands;
724 275325 : move16();
725 275325 : offsetSamples = imult1616( hSpatParamRendCom->slots_rendered, nBins );
726 : Word32 tmp_arr[CLDFB_NO_CHANNELS_MAX];
727 : /* Setup internal config */
728 275325 : config_data.separateCenterChannelRendering = st_ivas->hOutSetup.separateChannelEnabled;
729 275325 : move16();
730 275325 : config_data.ivas_format = st_ivas->ivas_format;
731 275325 : move32();
732 275325 : config_data.mc_mode = st_ivas->mc_mode;
733 275325 : move32();
734 275325 : config_data.ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate;
735 275325 : move32();
736 275325 : config_data.nchan_transport = st_ivas->nchan_transport;
737 275325 : move16();
738 275325 : IF( st_ivas->hMasa != NULL )
739 : {
740 92664 : config_data.qualityBasedSmFactor_fx = L_deposit_h( st_ivas->hMasa->data.dir_decode_quality_fx ); // Q31
741 : }
742 : ELSE
743 : {
744 182661 : config_data.qualityBasedSmFactor_fx = ONE_IN_Q31;
745 : }
746 275325 : move32();
747 275325 : IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) )
748 : {
749 118411 : config_data.processReverb = 1;
750 : }
751 : ELSE
752 : {
753 156914 : config_data.processReverb = 0;
754 : }
755 275325 : move16();
756 275325 : IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) )
757 : {
758 10085 : config_data.ism_mode = st_ivas->ism_mode;
759 : }
760 : ELSE
761 : {
762 265240 : config_data.ism_mode = ISM_MODE_NONE;
763 : }
764 275325 : move32();
765 :
766 : /* The input channel number at this processing function (not nchan_transport) */
767 275325 : numInChannels = BINAURAL_CHANNELS;
768 275325 : move16();
769 275325 : test();
770 275325 : test();
771 275325 : test();
772 275325 : test();
773 275325 : test();
774 275325 : test();
775 275325 : IF( config_data.separateCenterChannelRendering || ( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) && ( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) ) ) )
776 : {
777 6795 : numInChannels = add( numInChannels, 1 );
778 : }
779 268530 : ELSE IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) && EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) && ( EQ_32( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) )
780 : {
781 2958 : numInChannels = add( numInChannels, st_ivas->nchan_ism );
782 : }
783 :
784 275325 : Rmat_fx[0][0] = ONE_IN_Q30;
785 275325 : Rmat_fx[0][1] = 0;
786 275325 : Rmat_fx[0][2] = 0;
787 275325 : move32();
788 275325 : move32();
789 275325 : move32();
790 :
791 275325 : Rmat_fx[1][0] = 0;
792 275325 : Rmat_fx[1][1] = ONE_IN_Q30;
793 275325 : Rmat_fx[1][2] = 0;
794 275325 : move32();
795 275325 : move32();
796 275325 : move32();
797 :
798 275325 : Rmat_fx[2][0] = 0;
799 275325 : Rmat_fx[2][1] = 0;
800 275325 : Rmat_fx[2][2] = ONE_IN_Q30;
801 275325 : move32();
802 275325 : move32();
803 275325 : move32();
804 275325 : Word16 ch_len = s_max( 4, numInChannels );
805 1927275 : FOR( i = 0; i < 6; i++ )
806 : {
807 8259750 : FOR( j = 0; j < 4; j++ )
808 : {
809 6607800 : set32_fx( Cldfb_RealBuffer_in_fx[i][j], 0, 60 );
810 6607800 : set32_fx( Cldfb_ImagBuffer_in_fx[i][j], 0, 60 );
811 : }
812 : }
813 : /* CLDFB Analysis of input */
814 1373046 : FOR( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ )
815 : {
816 3350189 : FOR( ch = 0; ch < numInChannels; ch++ )
817 : {
818 2252468 : test();
819 2252468 : IF( ch == 0 || EQ_16( nchan_transport, 2 ) )
820 : {
821 1757947 : q_cldfb[ch][slot] = q_cldfb_temp;
822 1757947 : move16();
823 1757947 : Copy_Scale_sig32( &( st_ivas->hTcBuffer->tc_fx[ch][nBins * slot + offsetSamples] ), tmp_arr, nBins, -1 );
824 1757947 : scale_sig32( st_ivas->cldfbAnaDec[ch]->cldfb_state_fx, sub( st_ivas->cldfbAnaDec[ch]->p_filter_length, st_ivas->cldfbAnaDec[ch]->no_channels ), sub( q_cldfb_temp, st_ivas->cldfbAnaDec[ch]->Q_cldfb_state ) );
825 1757947 : cldfbAnalysis_ts_fx_fixed_q(
826 : tmp_arr,
827 1757947 : Cldfb_RealBuffer_in_fx[ch][slot],
828 1757947 : Cldfb_ImagBuffer_in_fx[ch][slot],
829 1757947 : nBins, st_ivas->cldfbAnaDec[ch], &q_cldfb[ch][slot] );
830 1757947 : scale_sig32( st_ivas->cldfbAnaDec[ch]->cldfb_state_fx, sub( st_ivas->cldfbAnaDec[ch]->p_filter_length, st_ivas->cldfbAnaDec[ch]->no_channels ), sub( q_input, st_ivas->cldfbAnaDec[ch]->Q_cldfb_state ) );
831 1757947 : st_ivas->cldfbAnaDec[ch]->Q_cldfb_state = q_input;
832 1757947 : scale_sig32( Cldfb_RealBuffer_in_fx[ch][slot], nBins, 1 ); // Q6
833 1757947 : scale_sig32( Cldfb_ImagBuffer_in_fx[ch][slot], nBins, 1 ); // Q6
834 1757947 : q_cldfb[ch][slot] = add( q_cldfb[ch][slot], 1 );
835 1757947 : move16();
836 : }
837 494521 : ELSE IF( EQ_16( config_data.nchan_transport, 2 ) ) /* Stereo signal transmitted as mono with DFT stereo */
838 : {
839 : /* At mono input duplicate the channel to dual-mono */
840 19396 : Copy32( Cldfb_RealBuffer_in_fx[0][slot], Cldfb_RealBuffer_in_fx[1][slot], nBins );
841 19396 : Copy32( Cldfb_ImagBuffer_in_fx[0][slot], Cldfb_ImagBuffer_in_fx[1][slot], nBins );
842 19396 : q_cldfb[1][slot] = q_cldfb[0][slot];
843 19396 : move16();
844 : }
845 : ELSE /* when nchan_transport == 1 and ch == 1 */
846 : {
847 : /* CNA and HB FD-CNG*/
848 475125 : test();
849 475125 : IF( st_ivas->hSCE[0]->hCoreCoder[0] != NULL && st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag )
850 266722 : {
851 : Word16 numCoreBands, b;
852 :
853 266722 : numCoreBands = st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->numCoreBands;
854 266722 : move16();
855 :
856 800166 : generate_masking_noise_dirac_ivas_fx( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom,
857 : st_ivas->cldfbAnaDec[1],
858 266722 : &st_ivas->hTcBuffer->tc_fx[nchan_transport][hSpatParamRendCom->num_freq_bands * hSpatParamRendCom->slots_rendered],
859 266722 : Cldfb_RealBuffer_in_fx[2][slot], Cldfb_ImagBuffer_in_fx[2][slot],
860 : slot,
861 266722 : st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->hSCE[0]->hCoreCoder[0]->flag_cna,
862 266722 : ( 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,
863 266722 : 11, &q_cldfb[2][slot] );
864 :
865 800166 : generate_masking_noise_dirac_ivas_fx( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom,
866 : st_ivas->cldfbAnaDec[1], /*nothing will be analyzed, just get cnst*/
867 : NULL,
868 266722 : Cldfb_RealBuffer_in_fx[1][slot], Cldfb_ImagBuffer_in_fx[1][slot],
869 : slot,
870 266722 : st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->hSCE[0]->hCoreCoder[0]->flag_cna,
871 266722 : ( 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,
872 266722 : 0, &q_cldfb[1][slot] );
873 :
874 266722 : scale_sig32( Cldfb_RealBuffer_in_fx[1][slot], CLDFB_NO_CHANNELS_MAX, negate( add( sub( q_cldfb[1][slot], q_input ), 5 ) ) );
875 266722 : scale_sig32( Cldfb_ImagBuffer_in_fx[1][slot], CLDFB_NO_CHANNELS_MAX, negate( add( sub( q_cldfb[1][slot], q_input ), 5 ) ) );
876 :
877 : /* LB: Copy first channel + LB-CNG to first and second channels with same scaling (dual-mono)*/
878 5468106 : FOR( b = 0; b < numCoreBands; b++ )
879 : {
880 5201384 : Cldfb_RealBuffer_in_fx[0][slot][b] = Mpy_32_16_1( L_add( L_shr( Cldfb_RealBuffer_in_fx[0][slot][b], add( sub( q_cldfb[0][slot], q_input ), 5 ) ), L_shr( Cldfb_RealBuffer_in_fx[2][slot][b], add( sub( q_cldfb[2][slot], q_input ), 5 ) ) ), 23170 /* INV_SQRT2 in Q15*/ );
881 5201384 : Cldfb_RealBuffer_in_fx[1][slot][b] = Cldfb_RealBuffer_in_fx[0][slot][b];
882 5201384 : move32();
883 5201384 : move32();
884 5201384 : Cldfb_ImagBuffer_in_fx[0][slot][b] = Mpy_32_16_1( L_add( L_shr( Cldfb_ImagBuffer_in_fx[0][slot][b], add( sub( q_cldfb[0][slot], q_input ), 5 ) ), L_shr( Cldfb_ImagBuffer_in_fx[2][slot][b], add( sub( q_cldfb[2][slot], q_input ), 5 ) ) ), 23170 );
885 5201384 : Cldfb_ImagBuffer_in_fx[1][slot][b] = Cldfb_ImagBuffer_in_fx[0][slot][b];
886 5201384 : move32();
887 5201384 : move32();
888 : }
889 266722 : q_cldfb[1][slot] = sub( q_input, 5 );
890 266722 : q_cldfb[0][slot] = sub( q_input, 5 );
891 266722 : move16();
892 266722 : move16();
893 : /* HB: Copy first channel to second channel and add HB-CNGs with different scalings*/
894 10070258 : FOR( ; b < nBins; b++ )
895 : {
896 9803536 : Cldfb_RealBuffer_in_fx[0][slot][b] = Mpy_32_16_1( Cldfb_RealBuffer_in_fx[0][slot][b], 23170 );
897 9803536 : Cldfb_RealBuffer_in_fx[1][slot][b] = L_add( L_add( Cldfb_RealBuffer_in_fx[0][slot][b], L_shr( Cldfb_RealBuffer_in_fx[1][slot][b], 1 ) ), Cldfb_RealBuffer_in_fx[0][slot][b] );
898 9803536 : Cldfb_RealBuffer_in_fx[0][slot][b] = L_add( Cldfb_RealBuffer_in_fx[0][slot][b], L_shr( Cldfb_RealBuffer_in_fx[2][slot][b], 1 ) );
899 :
900 9803536 : Cldfb_ImagBuffer_in_fx[0][slot][b] = Mpy_32_16_1( Cldfb_ImagBuffer_in_fx[0][slot][b], 23170 );
901 9803536 : Cldfb_ImagBuffer_in_fx[1][slot][b] = L_add( Cldfb_ImagBuffer_in_fx[0][slot][b], L_shr( Cldfb_ImagBuffer_in_fx[1][slot][b], 1 ) );
902 9803536 : Cldfb_ImagBuffer_in_fx[0][slot][b] = L_add( Cldfb_ImagBuffer_in_fx[0][slot][b], L_shr( Cldfb_ImagBuffer_in_fx[2][slot][b], 1 ) );
903 9803536 : move32();
904 9803536 : move32();
905 9803536 : move32();
906 9803536 : move32();
907 9803536 : move32();
908 9803536 : move32();
909 : }
910 : }
911 : ELSE
912 : {
913 : /* At mono input duplicate the channel to dual-mono, and apply gain
914 : correction to ensure same overall level as in stereo mode */
915 208403 : v_multc_fixed_16( Cldfb_RealBuffer_in_fx[0][slot], 23170, Cldfb_RealBuffer_in_fx[0][slot], nBins );
916 208403 : v_multc_fixed_16( Cldfb_ImagBuffer_in_fx[0][slot], 23170, Cldfb_ImagBuffer_in_fx[0][slot], nBins );
917 :
918 208403 : Copy32( Cldfb_RealBuffer_in_fx[0][slot], Cldfb_RealBuffer_in_fx[1][slot], nBins );
919 208403 : Copy32( Cldfb_ImagBuffer_in_fx[0][slot], Cldfb_ImagBuffer_in_fx[1][slot], nBins );
920 208403 : q_cldfb[1][slot] = q_cldfb[0][slot];
921 208403 : move16();
922 : }
923 : }
924 : }
925 :
926 1097721 : IF( hDiracDecBin->useTdDecorr )
927 : {
928 1304919 : FOR( ch = BINAURAL_CHANNELS; ch < ( 2 * BINAURAL_CHANNELS ); ch++ )
929 : {
930 869946 : q_cldfb[ch][slot] = sub( q_input, 1 );
931 869946 : move16();
932 :
933 869946 : Copy_Scale_sig32( &( st_ivas->hTcBuffer->tc_fx[ch][nBins * slot + offsetSamples] ), tmp_arr, 60, -1 );
934 869946 : scale_sig32( st_ivas->cldfbAnaDec[ch]->cldfb_state_fx, sub( st_ivas->cldfbAnaDec[ch]->p_filter_length, st_ivas->cldfbAnaDec[ch]->no_channels ), sub( sub( q_input, 1 ), st_ivas->cldfbAnaDec[ch]->Q_cldfb_state ) );
935 869946 : st_ivas->cldfbAnaDec[ch]->Q_cldfb_state = sub( q_input, 1 );
936 869946 : move16();
937 :
938 869946 : cldfbAnalysis_ts_fx_fixed_q(
939 : tmp_arr,
940 869946 : Cldfb_RealBuffer_in_fx[ch][slot],
941 869946 : Cldfb_ImagBuffer_in_fx[ch][slot],
942 869946 : nBins, st_ivas->cldfbAnaDec[ch], &q_cldfb[ch][slot] );
943 :
944 869946 : scale_sig32( st_ivas->cldfbAnaDec[ch]->cldfb_state_fx, sub( st_ivas->cldfbAnaDec[ch]->p_filter_length, st_ivas->cldfbAnaDec[ch]->no_channels ), sub( q_input, st_ivas->cldfbAnaDec[ch]->Q_cldfb_state ) );
945 869946 : st_ivas->cldfbAnaDec[ch]->Q_cldfb_state = q_input;
946 869946 : move16();
947 :
948 869946 : test();
949 869946 : test();
950 869946 : IF( EQ_16( config_data.nchan_transport, 1 ) &&
951 : ( EQ_32( config_data.ivas_format, SBA_FORMAT ) || EQ_32( config_data.ivas_format, SBA_ISM_FORMAT ) ) )
952 : {
953 517124 : v_multc_fixed_16( Cldfb_RealBuffer_in_fx[ch][slot], 23170, Cldfb_RealBuffer_in_fx[ch][slot], nBins );
954 517124 : v_multc_fixed_16( Cldfb_ImagBuffer_in_fx[ch][slot], 23170, Cldfb_ImagBuffer_in_fx[ch][slot], nBins );
955 : }
956 : }
957 : }
958 : }
959 :
960 275325 : test();
961 275325 : IF( EQ_32( config_data.ivas_format, SBA_FORMAT ) || EQ_32( config_data.ivas_format, SBA_ISM_FORMAT ) )
962 : {
963 150768 : hDiracDecBin->hDiffuseDist = &diffuseDistData;
964 150768 : ivas_spar_param_to_masa_param_mapping_fx( st_ivas, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_cldfb, subframe );
965 :
966 150768 : Scale_sig( st_ivas->hSpar->hFbMixer->cldfb_cross_fade_fx, CLDFB_NO_COL_MAX, Q15 - st_ivas->hSpar->hFbMixer->cldfb_cross_fade_q );
967 150768 : st_ivas->hSpar->hFbMixer->cldfb_cross_fade_q = Q15;
968 150768 : move16();
969 150768 : ivas_sba_prototype_renderer_fx( st_ivas, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_cldfb, subframe );
970 : }
971 :
972 275325 : Word16 q_inp = Q6;
973 275325 : move16();
974 1378793 : FOR( Word16 cha = 0; cha < ch_len; cha++ )
975 : {
976 5517340 : FOR( slot = 0; slot < 4; slot++ )
977 : {
978 4413872 : Word16 q_diff = sub( q_inp, q_cldfb[cha][slot] );
979 4413872 : IF( q_diff != 0 )
980 : {
981 3363986 : Scale_sig32( Cldfb_RealBuffer_in_fx[cha][slot], 60, q_diff ); // Q6
982 3363986 : Scale_sig32( Cldfb_ImagBuffer_in_fx[cha][slot], 60, q_diff ); // Q6
983 3363986 : q_cldfb[cha][slot] = 6;
984 : }
985 4413872 : move16();
986 : }
987 : }
988 :
989 275325 : test();
990 275325 : test();
991 275325 : test();
992 275325 : IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) && EQ_16( nchan_transport, 2 ) && NE_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) && NE_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) )
993 : {
994 : /* Un-tested function. No test-case is hitting.*/
995 2418 : ivas_omasa_preProcessStereoTransportsForMovedObjects_fx( st_ivas, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, &q_inp, nBins, subframe );
996 : }
997 :
998 275325 : IF( hCombinedOrientationData )
999 : {
1000 405888 : FOR( i = 0; i < 3; i++ )
1001 : {
1002 1217664 : FOR( j = 0; j < 3; j++ )
1003 : {
1004 913248 : Rmat_fx[i][j] = hCombinedOrientationData->Rmat_fx[hCombinedOrientationData->subframe_idx][i][j]; // Q30//
1005 913248 : move32();
1006 : }
1007 : }
1008 :
1009 101472 : IF( EQ_16( nchan_transport, 2 ) )
1010 : {
1011 : /* in case of split rendering, determine the prototype rotation based on the main direction and use the same prototypes for the offset directions */
1012 70800 : adaptTransportSignalsHeadtracked_fx( hCombinedOrientationData, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat_fx );
1013 70800 : ivas_dirac_dec_binaural_check_and_switch_transports_headtracked_fx( hCombinedOrientationData, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat_fx );
1014 : }
1015 : }
1016 :
1017 275325 : test();
1018 :
1019 275325 : IF( EQ_32( config_data.ivas_format, ISM_FORMAT ) )
1020 : {
1021 31893 : max_band_decorr = 0;
1022 31893 : move16();
1023 : }
1024 243432 : ELSE IF( hDiracDecBin->useTdDecorr )
1025 : {
1026 109053 : max_band_decorr = CLDFB_NO_CHANNELS_MAX;
1027 109053 : move16();
1028 : }
1029 : ELSE
1030 : {
1031 134379 : max_band_decorr = hDiracDecBin->h_freq_domain_decorr_ap_params->max_band_decorr;
1032 134379 : move16();
1033 : }
1034 :
1035 275325 : ivas_dirac_dec_binaural_formulate_input_covariance_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, subframe,
1036 : subFrameTotalEne_fx, subFrameTotalEne_e, IIReneLimiter_fx, q_inp );
1037 :
1038 275325 : ivas_dirac_dec_binaural_formulate_target_covariance_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat_fx, subframe,
1039 275325 : hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, subFrameTotalEne_fx, subFrameTotalEne_e, IIReneLimiter_fx, st_ivas->hMasaIsmData );
1040 :
1041 275325 : nchanSeparateChannels = 0;
1042 275325 : move16();
1043 275325 : test();
1044 275325 : test();
1045 275325 : test();
1046 275325 : test();
1047 275325 : test();
1048 275325 : test();
1049 275325 : IF( config_data.separateCenterChannelRendering || ( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) && ( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) ) ) )
1050 : {
1051 6795 : nchanSeparateChannels = 1;
1052 6795 : move16();
1053 : }
1054 268530 : ELSE IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) && EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) && ( EQ_32( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) )
1055 : {
1056 2958 : nchanSeparateChannels = (UWord8) st_ivas->nchan_ism;
1057 2958 : move16();
1058 : }
1059 :
1060 275325 : ivas_dirac_dec_binaural_determine_processing_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat_fx, subframe, hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, nchanSeparateChannels, st_ivas->hMasaIsmData );
1061 :
1062 275325 : q_inp = Q6;
1063 275325 : move16();
1064 825975 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1065 : {
1066 550650 : st_ivas->cldfbSynDec[ch]->Q_cldfb_state = Q11;
1067 550650 : move16();
1068 : }
1069 :
1070 275325 : q_mat = hDiracDecBin->q_processMtx;
1071 275325 : move16();
1072 275325 : q_mat = s_min( q_mat, hDiracDecBin->q_processMtxPrev );
1073 275325 : q_mat = s_min( q_mat, hDiracDecBin->q_processMtxDec );
1074 275325 : q_mat = s_min( q_mat, hDiracDecBin->q_processMtxDecPrev );
1075 :
1076 825975 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1077 : {
1078 1651950 : FOR( slot = 0; slot < BINAURAL_CHANNELS; slot++ )
1079 : {
1080 1101300 : Scale_sig( hDiracDecBin->processMtxRe_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) ); // scaling to q_mat
1081 1101300 : Scale_sig( hDiracDecBin->processMtxIm_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) ); // scaling to q_mat
1082 1101300 : Scale_sig( hDiracDecBin->processMtxRePrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); // scaling to q_mat
1083 1101300 : Scale_sig( hDiracDecBin->processMtxImPrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); // scaling to q_mat
1084 1101300 : Scale_sig( hDiracDecBin->processMtxDecRe_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDec ) ); // scaling to q_mat
1085 1101300 : Scale_sig( hDiracDecBin->processMtxDecIm_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDec ) ); // scaling to q_mat
1086 1101300 : Scale_sig( hDiracDecBin->processMtxDecRePrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDecPrev ) ); // scaling to q_mat
1087 1101300 : Scale_sig( hDiracDecBin->processMtxDecImPrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDecPrev ) ); // scaling to q_mat
1088 : }
1089 579708 : FOR( slot = 0; slot < nchanSeparateChannels; slot++ )
1090 : {
1091 29058 : Scale_sig( hDiracDecBin->processMtxRe_fx[ch][slot + BINAURAL_CHANNELS], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) ); // scaling to q_mat
1092 29058 : Scale_sig( hDiracDecBin->processMtxIm_fx[ch][slot + BINAURAL_CHANNELS], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) ); // scaling to q_mat
1093 29058 : Scale_sig( hDiracDecBin->processMtxRePrev_fx[ch][slot + BINAURAL_CHANNELS], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); // scaling to q_mat
1094 29058 : Scale_sig( hDiracDecBin->processMtxImPrev_fx[ch][slot + BINAURAL_CHANNELS], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); // scaling to q_mat
1095 : }
1096 : }
1097 275325 : hDiracDecBin->q_processMtx = q_mat;
1098 275325 : move16();
1099 275325 : hDiracDecBin->q_processMtxPrev = q_mat;
1100 275325 : move16();
1101 275325 : hDiracDecBin->q_processMtxDec = q_mat;
1102 275325 : move16();
1103 275325 : hDiracDecBin->q_processMtxDecPrev = q_mat;
1104 275325 : move16();
1105 :
1106 275325 : pMultiBinPoseData = NULL;
1107 275325 : IF( st_ivas->hSplitBinRend != NULL )
1108 : {
1109 0 : pMultiBinPoseData = &st_ivas->hSplitBinRend->splitrend.multiBinPoseData;
1110 0 : move32();
1111 : }
1112 :
1113 275325 : IF( EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) )
1114 : {
1115 0 : ivas_dirac_dec_binaural_process_output_fx( hDiracDecBin, hSpatParamRendCom, st_ivas->cldfbSynDec, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat,
1116 : tmp_Cldfb_out_re, tmp_Cldfb_out_im, reverbRe_fx, reverbIm_fx, decorrRe_fx, decorrIm_fx, &Q_inp_mix, 1 );
1117 :
1118 0 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1119 : {
1120 0 : FOR( i = 0; i < hSpatParamRendCom->subframe_nbslots[subframe]; i++ )
1121 : {
1122 0 : Copy32( tmp_Cldfb_out_re[ch][i], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural_fx[ch][hSpatParamRendCom->slots_rendered + i], CLDFB_NO_CHANNELS_MAX );
1123 0 : Copy32( tmp_Cldfb_out_im[ch][i], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural_fx[ch][hSpatParamRendCom->slots_rendered + i], CLDFB_NO_CHANNELS_MAX );
1124 : }
1125 : }
1126 : }
1127 : ELSE
1128 : {
1129 275325 : ivas_dirac_dec_binaural_process_output_fx( hDiracDecBin, hSpatParamRendCom, st_ivas->cldfbSynDec, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat, NULL, NULL,
1130 : reverbRe_fx, reverbIm_fx, decorrRe_fx, decorrIm_fx, &Q_inp_mix, 1 );
1131 : }
1132 275325 : hDiracDecBin->hDiffuseDist = NULL;
1133 :
1134 :
1135 275325 : if ( pMultiBinPoseData != NULL && pMultiBinPoseData->num_poses > 1 )
1136 : {
1137 : /* quaternion-based rotation from ivas_binRenderer_internal.c:ivas_binRenderer(), but using absolute rotation instead of delta rotations */
1138 : IVAS_QUATERNION Quaternions_rot, Quaternions_abs, *Quaternions_ref;
1139 : Word32 Rmat_local[3][3];
1140 :
1141 0 : if ( hCombinedOrientationData )
1142 : {
1143 0 : Quaternions_ref = &hCombinedOrientationData->Quaternions[0];
1144 0 : Copy_Quat_fx( Quaternions_ref, &Quaternions_abs );
1145 0 : modify_Quat_q_fx( &Quaternions_abs, &Quaternions_abs, Q22 );
1146 0 : Quaternions_rot.w_fx = L_negate( 12582912 ); /* signal to use Euler */
1147 0 : Quat2EulerDegree_fx( Quaternions_abs, &Quaternions_abs.z_fx, &Quaternions_abs.y_fx, &Quaternions_abs.x_fx ); /*order in Quat2Euler seems to be reversed ?*/
1148 0 : Quaternions_abs.w_fx = L_negate( 12582912 ); /* signal to use Euler */
1149 :
1150 0 : FOR( pos_idx = 1; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ )
1151 : {
1152 0 : Quaternions_rot.x_fx = L_add( Quaternions_abs.x_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][0] );
1153 0 : Quaternions_rot.y_fx = L_add( Quaternions_abs.y_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][1] );
1154 0 : Quaternions_rot.z_fx = L_add( Quaternions_abs.z_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][2] );
1155 0 : move32();
1156 0 : move32();
1157 0 : move32();
1158 0 : Euler2Quat_fx( deg2rad_fx( Quaternions_rot.x_fx ), deg2rad_fx( Quaternions_rot.y_fx ), deg2rad_fx( Quaternions_rot.z_fx ), &Quaternions_rot );
1159 0 : modify_Quat_q_fx( &Quaternions_rot, &Quaternions_rot, Quaternions_ref->q_fact );
1160 0 : QuatToRotMat_fx( Quaternions_rot, Rmat_local );
1161 0 : modify_Rmat_q_fx( Rmat_local, Rmat_local, sub( shl( Quaternions_ref->q_fact, 1 ), 32 ), Q30 );
1162 :
1163 0 : hDiracDecBin = st_ivas->hDiracDecBin[pos_idx];
1164 0 : assert( hDiracDecBin != NULL && "No DiracDecBin handle for this position" );
1165 0 : if ( config_data.ivas_format == SBA_FORMAT || config_data.ivas_format == SBA_ISM_FORMAT )
1166 : {
1167 0 : hDiracDecBin->hDiffuseDist = &diffuseDistData;
1168 : }
1169 :
1170 : /* re-use input covariance for the side renderings */
1171 0 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1172 : {
1173 0 : Copy32( st_ivas->hDiracDecBin[0]->ChEne_fx[ch], hDiracDecBin->ChEne_fx[ch], hSpatParamRendCom->num_freq_bands );
1174 0 : Copy( st_ivas->hDiracDecBin[0]->ChEne_e[ch], hDiracDecBin->ChEne_e[ch], hSpatParamRendCom->num_freq_bands );
1175 : }
1176 0 : Copy32( st_ivas->hDiracDecBin[0]->ChCrossRe_fx, hDiracDecBin->ChCrossRe_fx, hSpatParamRendCom->num_freq_bands );
1177 0 : Copy32( st_ivas->hDiracDecBin[0]->ChCrossIm_fx, hDiracDecBin->ChCrossIm_fx, hSpatParamRendCom->num_freq_bands );
1178 0 : Copy( st_ivas->hDiracDecBin[0]->ChCrossRe_e, hDiracDecBin->ChCrossRe_e, hSpatParamRendCom->num_freq_bands );
1179 0 : Copy( st_ivas->hDiracDecBin[0]->ChCrossIm_e, hDiracDecBin->ChCrossIm_e, hSpatParamRendCom->num_freq_bands );
1180 :
1181 0 : ivas_dirac_dec_binaural_formulate_target_covariance_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat_local, subframe,
1182 0 : hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0,
1183 : subFrameTotalEne_fx, subFrameTotalEne_e, IIReneLimiter_fx, st_ivas->hMasaIsmData );
1184 :
1185 0 : ivas_dirac_dec_binaural_determine_processing_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat_local, subframe,
1186 0 : hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0,
1187 : nchanSeparateChannels, st_ivas->hMasaIsmData );
1188 :
1189 :
1190 0 : q_mat = hDiracDecBin->q_processMtx;
1191 0 : move16();
1192 0 : q_mat = s_min( q_mat, hDiracDecBin->q_processMtxPrev );
1193 0 : q_mat = s_min( q_mat, hDiracDecBin->q_processMtxDec );
1194 0 : q_mat = s_min( q_mat, hDiracDecBin->q_processMtxDecPrev );
1195 :
1196 0 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1197 : {
1198 0 : FOR( slot = 0; slot < BINAURAL_CHANNELS; slot++ )
1199 : {
1200 0 : Scale_sig( hDiracDecBin->processMtxRe_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) ); // scaling to q_mat
1201 0 : Scale_sig( hDiracDecBin->processMtxIm_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) ); // scaling to q_mat
1202 0 : Scale_sig( hDiracDecBin->processMtxRePrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); // scaling to q_mat
1203 0 : Scale_sig( hDiracDecBin->processMtxImPrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); // scaling to q_mat
1204 0 : Scale_sig( hDiracDecBin->processMtxDecRe_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDec ) ); // scaling to q_mat
1205 0 : Scale_sig( hDiracDecBin->processMtxDecIm_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDec ) ); // scaling to q_mat
1206 0 : Scale_sig( hDiracDecBin->processMtxDecRePrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDecPrev ) ); // scaling to q_mat
1207 0 : Scale_sig( hDiracDecBin->processMtxDecImPrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDecPrev ) ); // scaling to q_mat
1208 : }
1209 0 : FOR( slot = 0; slot < nchanSeparateChannels; slot++ )
1210 : {
1211 0 : Scale_sig( hDiracDecBin->processMtxRe_fx[ch][slot + BINAURAL_CHANNELS], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) ); // scaling to q_mat
1212 0 : Scale_sig( hDiracDecBin->processMtxIm_fx[ch][slot + BINAURAL_CHANNELS], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) ); // scaling to q_mat
1213 0 : Scale_sig( hDiracDecBin->processMtxRePrev_fx[ch][slot + BINAURAL_CHANNELS], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); // scaling to q_mat
1214 0 : Scale_sig( hDiracDecBin->processMtxImPrev_fx[ch][slot + BINAURAL_CHANNELS], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); // scaling to q_mat
1215 : }
1216 : }
1217 0 : hDiracDecBin->q_processMtx = q_mat;
1218 0 : move16();
1219 0 : hDiracDecBin->q_processMtxPrev = q_mat;
1220 0 : move16();
1221 0 : hDiracDecBin->q_processMtxDec = q_mat;
1222 0 : move16();
1223 0 : hDiracDecBin->q_processMtxDecPrev = q_mat;
1224 0 : move16();
1225 :
1226 : /* re-use reverb and decorr from main direction for the sides */
1227 0 : ivas_dirac_dec_binaural_process_output_fx( hDiracDecBin, hSpatParamRendCom, st_ivas->cldfbSynDec, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat,
1228 : tmp_Cldfb_out_re, tmp_Cldfb_out_im, reverbRe_fx, reverbIm_fx, decorrRe_fx, decorrIm_fx, &Q_inp_mix, 0 );
1229 :
1230 : /* copy from temporary buffer to the main split rendering buffer */
1231 0 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1232 : {
1233 0 : FOR( i = 0; i < hSpatParamRendCom->subframe_nbslots[subframe]; i++ )
1234 : {
1235 0 : Copy32( tmp_Cldfb_out_re[ch][i], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural_fx[pos_idx * BINAURAL_CHANNELS + ch][hSpatParamRendCom->slots_rendered + i], CLDFB_NO_CHANNELS_MAX );
1236 0 : Copy32( tmp_Cldfb_out_im[ch][i], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural_fx[pos_idx * BINAURAL_CHANNELS + ch][hSpatParamRendCom->slots_rendered + i], CLDFB_NO_CHANNELS_MAX );
1237 : }
1238 : }
1239 :
1240 0 : hDiracDecBin->hDiffuseDist = NULL;
1241 : }
1242 : }
1243 : }
1244 :
1245 : /* update this counter only after the last rendering of split directions */
1246 :
1247 275325 : hSpatParamRendCom->slots_rendered = add( hSpatParamRendCom->slots_rendered, hSpatParamRendCom->subframe_nbslots[subframe] );
1248 275325 : hSpatParamRendCom->subframes_rendered = add( hSpatParamRendCom->subframes_rendered, 1 );
1249 :
1250 275325 : move16();
1251 275325 : move16();
1252 825975 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1253 : {
1254 550650 : scale_sig32( output_fx[ch], imult1616( nBins, hSpatParamRendCom->subframe_nbslots[subframe] ), sub( 11, q_out ) ); // Scaling to Q11
1255 550650 : scale_sig32( st_ivas->cldfbSynDec[ch]->cldfb_state_fx, st_ivas->cldfbSynDec[ch]->cldfb_size, sub( Q11, st_ivas->cldfbSynDec[ch]->Q_cldfb_state ) );
1256 550650 : st_ivas->cldfbSynDec[ch]->Q_cldfb_state = Q11;
1257 550650 : move16();
1258 : }
1259 :
1260 275325 : return;
1261 : }
1262 :
1263 :
1264 564275 : static void ivas_dirac_dec_decorrelate_slot_fx(
1265 : DIRAC_DEC_BIN_HANDLE hDiracDecBin,
1266 : const Word16 num_freq_bands,
1267 : const Word16 slot,
1268 : Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*q_inp*/
1269 : Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*q_inp*/
1270 : Word16 q_inp,
1271 : Word32 decRe[][CLDFB_NO_CHANNELS_MAX], /*q_inp*/
1272 : Word32 decIm[][CLDFB_NO_CHANNELS_MAX] /*q_inp*/ )
1273 : {
1274 : Word16 offset, ch, bin;
1275 : Word32 onset_filter_fx[BINAURAL_CHANNELS * CLDFB_NO_CHANNELS_MAX]; /* 2 ch, 60 bins */
1276 : Word32 decorrelatedFrameInterleaved_fx[2 * BINAURAL_CHANNELS * CLDFB_NO_CHANNELS_MAX]; /* 2 ch, real + imag, 60 bins */
1277 : Word32 protoFrame_fx[2 * BINAURAL_CHANNELS * CLDFB_NO_CHANNELS_MAX]; /* 2 ch, real + imag, 60 bins */
1278 : Word16 q_decorrelatedFrameInterleaved, q_protoFrame;
1279 564275 : const Word16 protoIndexDir[BINAURAL_CHANNELS] = { 0, 1 };
1280 564275 : move16();
1281 564275 : q_protoFrame = q_inp;
1282 564275 : move16();
1283 : /* Decorrelation needs interleaved data. Copy left and right signals to proto_frame_f */
1284 1692825 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1285 : {
1286 1128550 : offset = imult1616( imult1616( num_freq_bands, BINAURAL_CHANNELS ), ch );
1287 54483230 : FOR( bin = 0; bin < num_freq_bands; bin++ )
1288 : {
1289 53354680 : protoFrame_fx[add( imult1616( bin, BINAURAL_CHANNELS ), offset )] = inRe[ch][slot][bin]; // q_protoFrame
1290 53354680 : protoFrame_fx[add( imult1616( bin, BINAURAL_CHANNELS ), add( offset, 1 ) )] = inIm[ch][slot][bin]; // q_protoFrame
1291 53354680 : move32();
1292 53354680 : move32();
1293 : }
1294 : }
1295 :
1296 : /* Decorrelate proto signal to decorrelatedFrameInterleaved */
1297 564275 : ivas_dirac_dec_decorr_process_fx( num_freq_bands,
1298 : BINAURAL_CHANNELS,
1299 : BINAURAL_CHANNELS,
1300 : DIRAC_SYNTHESIS_PSD_LS,
1301 : BINAURAL_CHANNELS,
1302 : protoFrame_fx,
1303 : q_protoFrame,
1304 : BINAURAL_CHANNELS,
1305 : protoIndexDir,
1306 : decorrelatedFrameInterleaved_fx,
1307 : &q_decorrelatedFrameInterleaved,
1308 : onset_filter_fx,
1309 : hDiracDecBin->h_freq_domain_decorr_ap_params,
1310 : hDiracDecBin->h_freq_domain_decorr_ap_state );
1311 :
1312 : /* De-interleave decorrelated signals*/
1313 1692825 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1314 : {
1315 1128550 : offset = imult1616( imult1616( num_freq_bands, BINAURAL_CHANNELS ), ch );
1316 54483230 : FOR( bin = 0; bin < num_freq_bands; bin++ )
1317 : {
1318 53354680 : decRe[ch][bin] = decorrelatedFrameInterleaved_fx[add( imult1616( bin, BINAURAL_CHANNELS ), offset )]; // q_inp
1319 53354680 : decIm[ch][bin] = decorrelatedFrameInterleaved_fx[add( imult1616( bin, BINAURAL_CHANNELS ), add( offset, 1 ) )]; // q_inp
1320 53354680 : move32();
1321 53354680 : move32();
1322 : }
1323 : }
1324 : // q_decorrelatedFrameInterleaved will be same as q_inp/q_protoFrame //
1325 564275 : return;
1326 : }
1327 :
1328 :
1329 282525 : static void ivas_dirac_dec_binaural_formulate_input_covariance_matrices_fx(
1330 : DIRAC_DEC_BIN_HANDLE hDiracDecBin,
1331 : SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom,
1332 : PARAMBIN_REND_CONFIG_HANDLE hConfig,
1333 : Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*q*/
1334 : Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*q*/
1335 : const Word16 subframe,
1336 : Word32 *subFrameTotalEne_fx,
1337 : Word16 *subFrameTotalEne_e,
1338 : Word32 *IIReneLimiter_fx,
1339 : Word16 q )
1340 : {
1341 : Word16 ch, slot, bin;
1342 : Word16 nBins;
1343 : Word32 IIReneLimiterFactor_fx; // Q26
1344 : Word32 qualityBasedSmFactor_fx;
1345 : Word32 lowBitRateEQ_fx[CLDFB_NO_CHANNELS_MAX];
1346 : UWord8 applyLowBitRateEQ;
1347 : IVAS_FORMAT ivas_format;
1348 : Word32 ivas_total_brate;
1349 : Word16 nchan_transport;
1350 : Word16 exp, exp1;
1351 : Word64 temp64;
1352 : Word32 temp;
1353 :
1354 282525 : ivas_format = hConfig->ivas_format;
1355 282525 : move32();
1356 282525 : ivas_total_brate = hConfig->ivas_total_brate;
1357 282525 : move32();
1358 282525 : nchan_transport = hConfig->nchan_transport;
1359 282525 : move16();
1360 282525 : qualityBasedSmFactor_fx = hConfig->qualityBasedSmFactor_fx; /*Q31*/
1361 282525 : move32();
1362 282525 : qualityBasedSmFactor_fx = Mpy_32_32( qualityBasedSmFactor_fx, qualityBasedSmFactor_fx ); /*Q31*/
1363 :
1364 282525 : nBins = hSpatParamRendCom->num_freq_bands; /* Actually bins */
1365 282525 : move16();
1366 :
1367 :
1368 282525 : set32_fx( hDiracDecBin->ChCrossRe_fx, 0, nBins );
1369 282525 : set32_fx( hDiracDecBin->ChCrossIm_fx, 0, nBins );
1370 :
1371 :
1372 282525 : set16_fx( hDiracDecBin->ChCrossRe_e, 0, nBins );
1373 282525 : set16_fx( hDiracDecBin->ChCrossIm_e, 0, nBins );
1374 :
1375 847575 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1376 : {
1377 565050 : set32_fx( hDiracDecBin->ChEne_fx[ch], 0, nBins );
1378 :
1379 565050 : set16_fx( hDiracDecBin->ChEne_e[ch], 0, nBins );
1380 : }
1381 :
1382 282525 : set16_fx( subFrameTotalEne_e, 0, CLDFB_NO_CHANNELS_MAX );
1383 :
1384 : /* Determine EQ for low bit rates (13.2 and 16.4 kbps) */
1385 282525 : applyLowBitRateEQ = 0;
1386 282525 : move16();
1387 282525 : test();
1388 282525 : test();
1389 282525 : IF( ( EQ_32( ivas_format, MASA_FORMAT ) || EQ_32( ivas_format, MC_FORMAT ) ) && LT_32( ivas_total_brate, MASA_STEREO_MIN_BITRATE ) )
1390 : {
1391 10979 : applyLowBitRateEQ = 1;
1392 10979 : move16();
1393 10979 : IF( EQ_32( ivas_total_brate, IVAS_16k4 ) )
1394 : {
1395 78084 : FOR( bin = 0; bin < LOW_BIT_RATE_BINAURAL_EQ_BINS; bin++ )
1396 : {
1397 73746 : lowBitRateEQ_fx[bin + LOW_BIT_RATE_BINAURAL_EQ_OFFSET] = L_add( L_shr( lowBitRateBinauralEQ_fx[bin], 1 ), ONE_IN_Q30 ); // Q31
1398 73746 : move32();
1399 : }
1400 : }
1401 : ELSE
1402 : {
1403 119538 : FOR( bin = 0; bin < LOW_BIT_RATE_BINAURAL_EQ_BINS; bin++ )
1404 : {
1405 112897 : lowBitRateEQ_fx[bin + LOW_BIT_RATE_BINAURAL_EQ_OFFSET] = lowBitRateBinauralEQ_fx[bin]; // Q31
1406 112897 : move32();
1407 : }
1408 : }
1409 : }
1410 :
1411 : /* Formulate input and target covariance matrices for this subframe */
1412 282525 : set32_fx( subFrameTotalEne_fx, 0, CLDFB_NO_CHANNELS_MAX );
1413 :
1414 282525 : exp = sub( 63, shl( q, 1 ) ); // exp for the energy (inRe_fx * inRe_fx + inIm_fx * inIm_fx) computed below
1415 :
1416 : /* Calculate input covariance matrix */
1417 1409046 : FOR( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ )
1418 : {
1419 56624661 : FOR( bin = 0; bin < nBins; bin++ )
1420 : {
1421 166494420 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1422 : {
1423 : Word32 instEne_fx;
1424 110996280 : temp64 = W_mult0_32_32( inRe_fx[ch][slot][bin], inRe_fx[ch][slot][bin] ); // 2q
1425 110996280 : temp64 = W_add( temp64, W_mult0_32_32( inIm_fx[ch][slot][bin], inIm_fx[ch][slot][bin] ) ); // 2q
1426 110996280 : exp1 = W_norm( temp64 );
1427 110996280 : instEne_fx = W_extract_h( W_shl( temp64, exp1 ) ); // 2q - 32 + exp1
1428 : /* exp of instEne_fx = 31 - (2q -32 + exp1) = 63 - 2q - exp1 = exp - exp1*/
1429 :
1430 110996280 : hDiracDecBin->ChEne_fx[ch][bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEne_fx[ch][bin], hDiracDecBin->ChEne_e[ch][bin], instEne_fx, sub( exp, exp1 ), &hDiracDecBin->ChEne_e[ch][bin] );
1431 110996280 : subFrameTotalEne_fx[bin] = BASOP_Util_Add_Mant32Exp( subFrameTotalEne_fx[bin], subFrameTotalEne_e[bin], instEne_fx, sub( exp, exp1 ), &subFrameTotalEne_e[bin] );
1432 110996280 : move32();
1433 110996280 : move32();
1434 : }
1435 55498140 : temp64 = W_mult0_32_32( inRe_fx[0][slot][bin], inRe_fx[1][slot][bin] ); // 2q
1436 55498140 : temp64 = W_add( temp64, W_mult0_32_32( inIm_fx[0][slot][bin], inIm_fx[1][slot][bin] ) ); // 2q
1437 55498140 : exp1 = W_norm( temp64 );
1438 55498140 : temp = W_extract_h( W_shl( temp64, exp1 ) ); // // 2q - 32 + exp1
1439 55498140 : hDiracDecBin->ChCrossRe_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossRe_fx[bin], hDiracDecBin->ChCrossRe_e[bin], temp, sub( exp, exp1 ), &hDiracDecBin->ChCrossRe_e[bin] );
1440 55498140 : move32();
1441 :
1442 55498140 : temp64 = W_mult0_32_32( inRe_fx[0][slot][bin], inIm_fx[1][slot][bin] ); // 2q
1443 55498140 : temp64 = W_sub( temp64, W_mult0_32_32( inIm_fx[0][slot][bin], inRe_fx[1][slot][bin] ) ); // 2q
1444 55498140 : exp1 = W_norm( temp64 );
1445 55498140 : temp = W_extract_h( W_shl( temp64, exp1 ) ); // // 2q - 32 + exp1
1446 55498140 : hDiracDecBin->ChCrossIm_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossIm_fx[bin], hDiracDecBin->ChCrossIm_e[bin], temp, sub( exp, exp1 ), &hDiracDecBin->ChCrossIm_e[bin] );
1447 55498140 : move32();
1448 : }
1449 : }
1450 :
1451 : /* Apply EQ at low bit rates */
1452 282525 : IF( applyLowBitRateEQ != 0 )
1453 : {
1454 10979 : Word16 lastEqBin = LOW_BIT_RATE_BINAURAL_EQ_OFFSET + LOW_BIT_RATE_BINAURAL_EQ_BINS - 1;
1455 :
1456 186643 : FOR( bin = LOW_BIT_RATE_BINAURAL_EQ_OFFSET; bin < lastEqBin; bin++ )
1457 : {
1458 175664 : subFrameTotalEne_fx[bin] = Mpy_32_32( subFrameTotalEne_fx[bin], lowBitRateEQ_fx[bin] ); // exp = subFrameTotalEne_e[bin]
1459 175664 : move32();
1460 : }
1461 275279 : FOR( ; bin < nBins; bin++ )
1462 : {
1463 264300 : subFrameTotalEne_fx[bin] = Mpy_32_32( subFrameTotalEne_fx[bin], lowBitRateEQ_fx[lastEqBin] ); // exp = subFrameTotalEne_e[bin]
1464 264300 : move32();
1465 : }
1466 : }
1467 :
1468 282525 : test();
1469 282525 : test();
1470 282525 : IF( ( EQ_32( ivas_format, SBA_FORMAT ) || EQ_32( ivas_format, SBA_ISM_FORMAT ) ) && EQ_16( nchan_transport, 2 ) )
1471 : {
1472 : Word32 tempRe, tempIm;
1473 : Word32 subFrameSumEne_fx[CLDFB_NO_CHANNELS_MAX];
1474 : Word16 subFrameSumEne_e[CLDFB_NO_CHANNELS_MAX];
1475 :
1476 85934 : set32_fx( subFrameSumEne_fx, 0, CLDFB_NO_CHANNELS_MAX );
1477 85934 : set16_fx( subFrameSumEne_e, 0, CLDFB_NO_CHANNELS_MAX );
1478 428675 : FOR( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ )
1479 : {
1480 15063361 : FOR( bin = 0; bin < nBins; bin++ )
1481 : {
1482 14720620 : tempRe = L_add( inRe_fx[0][slot][bin], inRe_fx[1][slot][bin] ); // q
1483 14720620 : tempIm = L_add( inIm_fx[0][slot][bin], inIm_fx[1][slot][bin] ); // q
1484 14720620 : temp64 = W_add( W_mult0_32_32( tempRe, tempRe ), W_mult0_32_32( tempIm, tempIm ) ); // 2q
1485 14720620 : exp1 = W_norm( temp64 );
1486 14720620 : temp64 = W_shl( temp64, exp1 ); // 2q + exp1
1487 14720620 : subFrameSumEne_fx[bin] = BASOP_Util_Add_Mant32Exp( subFrameSumEne_fx[bin], subFrameSumEne_e[bin], W_extract_h( temp64 ), sub( exp /* 63 - 2q */, exp1 ) /*31 - (2q + exp1 - 32)*/, &subFrameSumEne_e[bin] );
1488 14720620 : move32();
1489 : }
1490 : }
1491 3781014 : FOR( bin = 0; bin < nBins; bin++ )
1492 : {
1493 3695080 : subFrameTotalEne_e[bin] = sub( subFrameTotalEne_e[bin], 1 );
1494 3695080 : move16();
1495 3695080 : temp = L_shl_sat( subFrameTotalEne_fx[bin], sub( subFrameTotalEne_e[bin], subFrameSumEne_e[bin] ) ); // subFrameSumEne_e[bin]
1496 3695080 : IF( GT_32( subFrameSumEne_fx[bin], temp ) )
1497 : {
1498 3580523 : subFrameTotalEne_fx[bin] = subFrameSumEne_fx[bin];
1499 3580523 : move32();
1500 3580523 : subFrameTotalEne_e[bin] = subFrameSumEne_e[bin];
1501 3580523 : move16();
1502 : }
1503 : }
1504 : }
1505 :
1506 :
1507 282525 : test();
1508 : /* Temporal IIR-type smoothing of covariance matrices. Also apply encoding quality based smoothing factor. */
1509 282525 : IF( EQ_32( ivas_format, MASA_FORMAT ) && LT_32( ivas_total_brate, MASA_STEREO_MIN_BITRATE ) )
1510 : {
1511 9559 : IIReneLimiterFactor_fx = L_add( L_shl( 16, Q26 ), L_sub( L_shl( 1, Q26 ), L_shr( qualityBasedSmFactor_fx, 5 ) ) ); // Q26
1512 : }
1513 : ELSE
1514 : {
1515 272966 : IIReneLimiterFactor_fx = L_add( L_shl( 8, Q26 ), L_sub( L_shl( 1, Q26 ), L_shr( qualityBasedSmFactor_fx, 5 ) ) ); // Q26
1516 : }
1517 :
1518 14200945 : FOR( bin = 0; bin < nBins; bin++ )
1519 : {
1520 :
1521 : /* Temporally smooth cov mtx estimates for resulting mixing matrix stability. The design principle is that
1522 : * the energy history (IIR) must not be more than double of the current frame energy. This provides more
1523 : * robust performance at energy offsets when compared to typical IIR averaging. */
1524 : Word16 num_e, den_e;
1525 : Word32 num, den;
1526 13918420 : num = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEne_fx[0][bin], hDiracDecBin->ChEne_e[0][bin], hDiracDecBin->ChEne_fx[1][bin], hDiracDecBin->ChEne_e[1][bin], &num_e );
1527 13918420 : num = Mpy_32_32( num, IIReneLimiterFactor_fx ); /*Q = (31 - num_e + 26 - 31) = (26 - num_e)*/
1528 13918420 : den_e = 0;
1529 13918420 : move16();
1530 13918420 : den = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEnePrev_fx[0][bin], hDiracDecBin->ChEnePrev_e[0][bin], hDiracDecBin->ChEnePrev_fx[1][bin], hDiracDecBin->ChEnePrev_e[1][bin], &den_e );
1531 13918420 : den = L_max( 1, den );
1532 13918420 : IIReneLimiter_fx[bin] = BASOP_Util_Divide3232_Scale_cadence( num, den, &exp );
1533 13918420 : exp = add( sub( num_e, den_e ), add( 5, exp ) );
1534 13918420 : IF( L_shr_sat( IIReneLimiter_fx[bin], sub( 31, exp ) ) > 0 )
1535 : {
1536 8607236 : IIReneLimiter_fx[bin] = ONE_IN_Q31; /*Q31*/
1537 8607236 : move32();
1538 : }
1539 : ELSE
1540 : {
1541 5311184 : IIReneLimiter_fx[bin] = L_shl( IIReneLimiter_fx[bin], exp ); /*Q31*/
1542 : }
1543 :
1544 13918420 : hDiracDecBin->ChCrossRe_fx[bin] = Mpy_32_32( hDiracDecBin->ChCrossRe_fx[bin], qualityBasedSmFactor_fx );
1545 13918420 : hDiracDecBin->ChCrossIm_fx[bin] = Mpy_32_32( hDiracDecBin->ChCrossIm_fx[bin], qualityBasedSmFactor_fx );
1546 :
1547 13918420 : move32();
1548 13918420 : move32();
1549 13918420 : move32();
1550 13918420 : move32();
1551 :
1552 41755260 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1553 : {
1554 27836840 : hDiracDecBin->ChEne_fx[ch][bin] = Mpy_32_32( hDiracDecBin->ChEne_fx[ch][bin], qualityBasedSmFactor_fx );
1555 27836840 : move32();
1556 : }
1557 :
1558 13918420 : hDiracDecBin->ChCrossRe_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossRe_fx[bin], hDiracDecBin->ChCrossRe_e[bin], Mpy_32_32( hDiracDecBin->ChCrossRePrev_fx[bin], IIReneLimiter_fx[bin] ), hDiracDecBin->ChCrossRePrev_e[bin], &hDiracDecBin->ChCrossRe_e[bin] );
1559 13918420 : hDiracDecBin->ChCrossIm_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossIm_fx[bin], hDiracDecBin->ChCrossIm_e[bin], Mpy_32_32( hDiracDecBin->ChCrossImPrev_fx[bin], IIReneLimiter_fx[bin] ), hDiracDecBin->ChCrossImPrev_e[bin], &hDiracDecBin->ChCrossIm_e[bin] );
1560 13918420 : move32();
1561 13918420 : move32();
1562 :
1563 41755260 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1564 : {
1565 27836840 : hDiracDecBin->ChEne_fx[ch][bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEne_fx[ch][bin], hDiracDecBin->ChEne_e[ch][bin], Mpy_32_32( hDiracDecBin->ChEnePrev_fx[ch][bin], IIReneLimiter_fx[bin] ), hDiracDecBin->ChEnePrev_e[ch][bin], &hDiracDecBin->ChEne_e[ch][bin] );
1566 27836840 : move32();
1567 : }
1568 :
1569 : /* Store energy values and coefficients for next round */
1570 13918420 : hDiracDecBin->ChCrossRePrev_fx[bin] = hDiracDecBin->ChCrossRe_fx[bin];
1571 13918420 : move32();
1572 13918420 : hDiracDecBin->ChCrossImPrev_fx[bin] = hDiracDecBin->ChCrossIm_fx[bin];
1573 13918420 : move32();
1574 13918420 : hDiracDecBin->ChCrossRePrev_e[bin] = hDiracDecBin->ChCrossRe_e[bin];
1575 13918420 : move16();
1576 13918420 : hDiracDecBin->ChCrossImPrev_e[bin] = hDiracDecBin->ChCrossIm_e[bin];
1577 13918420 : move16();
1578 :
1579 41755260 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1580 : {
1581 27836840 : hDiracDecBin->ChEnePrev_fx[ch][bin] = hDiracDecBin->ChEne_fx[ch][bin];
1582 27836840 : move32();
1583 27836840 : hDiracDecBin->ChEnePrev_e[ch][bin] = hDiracDecBin->ChEne_e[ch][bin];
1584 27836840 : move16();
1585 : }
1586 : }
1587 :
1588 282525 : return;
1589 : }
1590 :
1591 :
1592 282525 : static void ivas_dirac_dec_binaural_formulate_target_covariance_matrices_fx(
1593 : DIRAC_DEC_BIN_HANDLE hDiracDecBin,
1594 : const SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom,
1595 : const PARAMBIN_REND_CONFIG_HANDLE hConfig,
1596 : Word32 Rmat_fx[3][3],
1597 : const Word16 subframe,
1598 : const Word16 isHeadtracked,
1599 : const Word32 *subFrameTotalEne_fx,
1600 : Word16 *subFrameTotalEne_e,
1601 : const Word32 *IIReneLimiter_fx,
1602 : const MASA_ISM_DATA_HANDLE hMasaIsmData )
1603 : {
1604 : Word16 ch, bin;
1605 : Word16 separateCenterChannelRendering;
1606 : Word16 nBins, idx, shift;
1607 : Word32 frameMeanDiffusenessEneWeight_fx[CLDFB_NO_CHANNELS_MAX];
1608 : Word32 qualityBasedSmFactor_fx;
1609 : Word16 dirac_read_idx;
1610 : PARAMBIN_HRTF_GAIN_CACHE gainCache[MAX_GAIN_CACHE_SIZE];
1611 : IVAS_FORMAT ivas_format;
1612 : MC_MODE mc_mode;
1613 : Word16 gainCacheBaseIndex;
1614 : Word16 q_earlyPartEneCorrection;
1615 : Word16 exp, exp1;
1616 : Word32 temp;
1617 :
1618 282525 : separateCenterChannelRendering = hConfig->separateCenterChannelRendering;
1619 282525 : move16();
1620 282525 : ivas_format = hConfig->ivas_format;
1621 282525 : move32();
1622 282525 : mc_mode = hConfig->mc_mode;
1623 282525 : move32();
1624 282525 : qualityBasedSmFactor_fx = hConfig->qualityBasedSmFactor_fx; /*Q31*/
1625 282525 : move32();
1626 282525 : qualityBasedSmFactor_fx = Mpy_32_32( qualityBasedSmFactor_fx, qualityBasedSmFactor_fx ); /*Q31*/
1627 :
1628 282525 : nBins = hSpatParamRendCom->num_freq_bands; /* Actually bins */
1629 282525 : move16();
1630 :
1631 282525 : q_earlyPartEneCorrection = s_min( Q31, add( getScaleFactor32( hDiracDecBin->earlyPartEneCorrection_fx, nBins ), hDiracDecBin->q_earlyPartEneCorrection ) );
1632 282525 : scale_sig32( hDiracDecBin->earlyPartEneCorrection_fx, nBins, sub( q_earlyPartEneCorrection, hDiracDecBin->q_earlyPartEneCorrection ) );
1633 282525 : hDiracDecBin->q_earlyPartEneCorrection = q_earlyPartEneCorrection;
1634 282525 : move16();
1635 :
1636 282525 : set32_fx( hDiracDecBin->ChCrossReOut_fx, 0, nBins );
1637 282525 : set32_fx( hDiracDecBin->ChCrossImOut_fx, 0, nBins );
1638 282525 : set16_fx( hDiracDecBin->ChCrossReOut_e, 0, nBins );
1639 282525 : set16_fx( hDiracDecBin->ChCrossImOut_e, 0, nBins );
1640 :
1641 847575 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
1642 : {
1643 565050 : set32_fx( hDiracDecBin->ChEneOut_fx[ch], 0, nBins );
1644 565050 : set16_fx( hDiracDecBin->ChEneOut_e[ch], 0, nBins );
1645 : }
1646 282525 : set32_fx( hDiracDecBin->frameMeanDiffuseness_fx, 0, nBins );
1647 :
1648 282525 : set32_fx( frameMeanDiffusenessEneWeight_fx, 0, CLDFB_NO_CHANNELS_MAX );
1649 :
1650 3107775 : FOR( idx = 0; idx < MAX_GAIN_CACHE_SIZE; idx++ )
1651 : {
1652 2825250 : gainCache[idx].azi = -1000; /* Use -1000 as value for uninitialized cache. */
1653 2825250 : move16();
1654 : }
1655 :
1656 282525 : dirac_read_idx = hSpatParamRendCom->render_to_md_map[subframe];
1657 :
1658 : /* Determine target covariance matrix containing target binaural properties */
1659 14200945 : FOR( bin = 0; bin < nBins; bin++ )
1660 : {
1661 13918420 : Word32 diffuseness_fx = ONE_IN_Q30; /* ratio1 and ratio2 are subtracted from diffuseness further below */
1662 13918420 : Word32 diffusenessValForDecorrelationReduction_fx = ONE_IN_Q30;
1663 : Word32 diffEneValForDecorrelationReduction_fx;
1664 : Word16 q_diffEneValForDecorrelationReduction;
1665 13918420 : Word16 surCoh_fx = 0, spreadCoh_fx = 0; /* Default values if spreadSurroundCoherenceApplied == false */
1666 : Word32 diffEne_fx, dirEne_fx, meanEnePerCh_fx;
1667 : Word16 q_meanEnePerCh;
1668 : Word16 q_diffEne, q_dirEne;
1669 : Word16 dirIndex;
1670 13918420 : move16();
1671 13918420 : move16();
1672 13918420 : move32();
1673 13918420 : move32();
1674 :
1675 : /* When BINAURAL_ROOM is not indicated, hBinaural->earlyPartEneCorrection[bin] values are all 1.0f.
1676 : * When BINAURAL_ROOM is indicated, the binaural audio output is based on combined use of the
1677 : * HRTF data set and a BRIR-based data set. The HRTF data set is spectrally corrected to match
1678 : * the early spectrum of the BRIR data, using the spectral correction data in
1679 : * hBinaural->earlyPartEneCorrection[bin], based on the BRIR set. */
1680 13918420 : meanEnePerCh_fx = Mpy_32_32( hDiracDecBin->earlyPartEneCorrection_fx[bin], subFrameTotalEne_fx[bin] ); // Q( q_meanEnePerCh )
1681 13918420 : q_meanEnePerCh = add( sub( q_earlyPartEneCorrection, subFrameTotalEne_e[bin] ), 1 ); // q_earlyPartEneCorrection + 31 - subFrameTotalEne_e[bin] - 31 + Q1(0.5f)
1682 : /* Determine direct part target covariance matrix (for 1 or 2 directions) */
1683 30802220 : FOR( dirIndex = 0; dirIndex < hSpatParamRendCom->numSimultaneousDirections; dirIndex++ )
1684 : {
1685 : Word16 aziDeg, eleDeg;
1686 : Word32 lRealp_fx, lImagp_fx, rRealp_fx, rImagp_fx;
1687 : Word32 lRealpTmp_fx, lImagpTmp_fx, rRealpTmp_fx, rImagpTmp_fx;
1688 : Word32 hrtfEne_fx[BINAURAL_CHANNELS], hrtfCrossRe_fx, hrtfCrossIm_fx, ratio_fx;
1689 16883800 : UWord8 isIsmDirection = 0;
1690 16883800 : move16();
1691 :
1692 16883800 : test();
1693 16883800 : test();
1694 16883800 : IF( dirIndex == 0 ) /* For first of the two simultaneous directions */
1695 : {
1696 13918420 : aziDeg = hSpatParamRendCom->azimuth[dirac_read_idx][bin];
1697 13918420 : move16();
1698 13918420 : eleDeg = hSpatParamRendCom->elevation[dirac_read_idx][bin];
1699 13918420 : move16();
1700 13918420 : ratio_fx = hSpatParamRendCom->energy_ratio1_fx[dirac_read_idx][bin];
1701 13918420 : move32();
1702 13918420 : spreadCoh_fx = hSpatParamRendCom->spreadCoherence_fx[dirac_read_idx][bin];
1703 13918420 : move16();
1704 13918420 : gainCacheBaseIndex = 0;
1705 13918420 : move16();
1706 : }
1707 2965380 : ELSE IF( NE_32( ivas_format, MASA_ISM_FORMAT ) || ( EQ_32( ivas_format, MASA_ISM_FORMAT ) && LT_16( dirIndex, hSpatParamRendCom->numParametricDirections ) ) ) /* For second of the two simultaneous directions */
1708 : {
1709 2627220 : IF( LT_32( ( ratio_fx = hSpatParamRendCom->energy_ratio2_fx[dirac_read_idx][bin] ), 10737418 /* 0.01 in Q30 */ ) )
1710 : {
1711 : /* This touches only MASA path where second direction always has smaller ratio and
1712 : * for non-2dir it is zero. As the whole direction contribution is multiplied with
1713 : * the ratio, a very small ratio does not contribute any energy to output. Thus,
1714 : * it is better to save complexity. */
1715 1043373 : CONTINUE;
1716 : }
1717 1583847 : aziDeg = hSpatParamRendCom->azimuth2[dirac_read_idx][bin];
1718 1583847 : move16();
1719 1583847 : eleDeg = hSpatParamRendCom->elevation2[dirac_read_idx][bin];
1720 1583847 : move16();
1721 1583847 : spreadCoh_fx = hSpatParamRendCom->spreadCoherence2_fx[dirac_read_idx][bin];
1722 1583847 : move16();
1723 1583847 : gainCacheBaseIndex = 3;
1724 1583847 : move16();
1725 : }
1726 : ELSE /* For object directions of MASA_ISM_FORMAT */
1727 : {
1728 338160 : isIsmDirection = 1;
1729 338160 : move16();
1730 : UWord16 ismDirIndex;
1731 338160 : ismDirIndex = sub( dirIndex, hSpatParamRendCom->numParametricDirections );
1732 338160 : assert( hMasaIsmData != NULL && "hMasaIsmData should not be NULL if we use it" );
1733 338160 : IF( hMasaIsmData->ism_is_edited[ismDirIndex] )
1734 : {
1735 0 : aziDeg = hMasaIsmData->azimuth_ism_edited[ismDirIndex];
1736 0 : move16();
1737 0 : eleDeg = hMasaIsmData->elevation_ism_edited[ismDirIndex];
1738 0 : move16();
1739 : }
1740 : ELSE
1741 : {
1742 338160 : aziDeg = hMasaIsmData->azimuth_ism[ismDirIndex][dirac_read_idx];
1743 338160 : move16();
1744 338160 : eleDeg = hMasaIsmData->elevation_ism[ismDirIndex][dirac_read_idx];
1745 338160 : move16();
1746 : }
1747 338160 : ratio_fx = hMasaIsmData->energy_ratio_ism_fx[ismDirIndex][dirac_read_idx][bin];
1748 338160 : move32();
1749 338160 : spreadCoh_fx = 0;
1750 338160 : move16();
1751 338160 : gainCacheBaseIndex = add( 6, ismDirIndex );
1752 : }
1753 :
1754 15840427 : diffuseness_fx = L_sub( diffuseness_fx, ratio_fx ); /* diffuseness = 1 - ratio1 - ratio2 */
1755 :
1756 15840427 : if ( diffuseness_fx < 0 )
1757 : {
1758 13091 : diffuseness_fx = 0;
1759 13091 : move32();
1760 : }
1761 15840427 : IF( isIsmDirection )
1762 : {
1763 : /* Objects cause lesser decorrelation reduction, to avoid removing all decorrelation when only objects are present */
1764 338160 : diffusenessValForDecorrelationReduction_fx = L_sub( diffusenessValForDecorrelationReduction_fx, L_shr( ratio_fx, 1 ) ); /*Q30*/
1765 : }
1766 : ELSE
1767 : {
1768 15502267 : diffusenessValForDecorrelationReduction_fx = L_sub( diffusenessValForDecorrelationReduction_fx, ratio_fx ); /*Q30*/
1769 : }
1770 :
1771 15840427 : IF( separateCenterChannelRendering )
1772 : {
1773 : /* In masa + mono rendering mode, the center directions originate from phantom sources, so the
1774 : * spread coherence is increased */
1775 : Word16 azi_scaled, ele_scaled;
1776 : Word32 doaVectorX_fx, num, den;
1777 6000 : Word16 e = 0, spatialAngleDeg_fx, altSpreadCoh_fx;
1778 6000 : move16();
1779 :
1780 6000 : azi_scaled = i_mult( aziDeg, 91 );
1781 6000 : ele_scaled = i_mult( eleDeg, 91 );
1782 6000 : doaVectorX_fx = L_mult( getCosWord16R2( azi_scaled ), getCosWord16R2( ele_scaled ) ); /*Q31*/
1783 6000 : num = Sqrt32( L_sub( ONE_IN_Q31, Mpy_32_32( doaVectorX_fx, doaVectorX_fx ) ), &e );
1784 6000 : den = doaVectorX_fx;
1785 6000 : move32();
1786 6000 : spatialAngleDeg_fx = BASOP_util_atan2( num, den, e ); // Q13
1787 6000 : Word16 numr, num_e = 0, denr, den_e;
1788 6000 : move16();
1789 6000 : num_e = sub( norm_s( spatialAngleDeg_fx ), 1 );
1790 6000 : numr = shl( spatialAngleDeg_fx, num_e );
1791 6000 : denr = 17157;
1792 6000 : move16();
1793 6000 : den_e = 4;
1794 6000 : move16();
1795 6000 : altSpreadCoh_fx = sub( 32767, shl_sat( div_s( numr, denr ), sub( den_e, num_e ) ) ); // 4289 = pi/6 in Q13
1796 6000 : spreadCoh_fx = s_max( spreadCoh_fx, altSpreadCoh_fx );
1797 : }
1798 :
1799 : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
1800 15840427 : getDirectPartGains_fx( bin, aziDeg, eleDeg, &lRealp_fx, &lImagp_fx, &rRealp_fx, &rImagp_fx, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat_fx, &gainCache[gainCacheBaseIndex], isHeadtracked, *hDiracDecBin->phHrtfParambin );
1801 : #else
1802 : getDirectPartGains_fx( bin, aziDeg, eleDeg, &lRealp_fx, &lImagp_fx, &rRealp_fx, &rImagp_fx, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat_fx, &gainCache[gainCacheBaseIndex], isHeadtracked );
1803 : #endif
1804 :
1805 15840427 : Word16 q_lr = Q28;
1806 15840427 : move16();
1807 15840427 : if ( hDiracDecBin->renderStereoOutputInsteadOfBinaural )
1808 : {
1809 : /* Synthesizing spread coherence is not needed for stereo loudspeaker output,
1810 : * as directional sound is reproduced with two loudspeakers in any case */
1811 1255906 : spreadCoh_fx = 0;
1812 1255906 : move32();
1813 : }
1814 :
1815 15840427 : IF( spreadCoh_fx > 0 )
1816 : {
1817 : Word32 centerMul_fx, sidesMul_fx;
1818 : Word32 hrtfEneCenter_fx, hrtfEneSides_fx, hrtfEneRealized_fx;
1819 : Word16 eneCorrectionFactor_fx, eneCorrectionFactor_e;
1820 : Word16 w1_fx, w2_fx, w3_fx, eq_fx;
1821 :
1822 2138881 : hrtfEneCenter_fx = L_add( Mpy_32_32( lRealp_fx, lRealp_fx ), // Q25
1823 : L_add( Mpy_32_32( lImagp_fx, lImagp_fx ), // Q25
1824 : L_add( Mpy_32_32( rRealp_fx, rRealp_fx ), // Q25
1825 : Mpy_32_32( rImagp_fx, rImagp_fx ) ) ) ); // Q25
1826 :
1827 : /* Spread coherence is synthesized as coherent sources at 30 degree horizontal spacing.
1828 : * The following formulas determine the gains for these sources.
1829 : * spreadCoh = 0: Only panning
1830 : * spreadCoh = 0.5: Three sources coherent panning (e.g. 30 0 -30 deg azi)
1831 : * spreadCoh = 1.0: Two sources coherent panning with gap (as above, but center is silent) */
1832 2138881 : IF( LT_16( spreadCoh_fx, 16384 ) )
1833 : {
1834 : /* 0.0f < spreadCoh < 0.5f */
1835 1639747 : sidesMul_fx = L_mult0( spreadCoh_fx, 9459 ); /* 2*sqrt(1/3) in Q13 = 9459 */ // Q28
1836 1639747 : centerMul_fx = L_add( L_sub( ONE_IN_Q28, L_shl( spreadCoh_fx, 14 ) ), sidesMul_fx ); // Q28
1837 : }
1838 : ELSE
1839 : {
1840 : /* 0.5f <= spreadCoh < 1.0f */
1841 : // centerMul = 2.0f - ( 2.0f * spreadCoh );
1842 499134 : centerMul_fx = L_shl( sub( 32767, spreadCoh_fx ), 14 ); // Q28
1843 499134 : sidesMul_fx = Isqrt( L_add( L_shr( centerMul_fx, 22 ), L_shl( 2, Q6 ) ) ); // Q28
1844 499134 : centerMul_fx = L_shl( Mpy_32_32( centerMul_fx, sidesMul_fx ), 3 ); // Q28
1845 : }
1846 :
1847 : /* Apply the gain for the center source of the three coherent sources */
1848 2138881 : lRealp_fx = Mpy_32_32( lRealp_fx, centerMul_fx ); // Q25
1849 2138881 : lImagp_fx = Mpy_32_32( lImagp_fx, centerMul_fx ); // Q25
1850 2138881 : rRealp_fx = Mpy_32_32( rRealp_fx, centerMul_fx ); // Q25
1851 2138881 : rImagp_fx = Mpy_32_32( rImagp_fx, centerMul_fx ); // Q25
1852 :
1853 : /* Apply the gain for the left source of the three coherent sources */
1854 : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
1855 2138881 : getDirectPartGains_fx( bin, add( aziDeg, 30 ), eleDeg, &lRealpTmp_fx, &lImagpTmp_fx, &rRealpTmp_fx, &rImagpTmp_fx, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat_fx, &gainCache[gainCacheBaseIndex + 1], isHeadtracked, *hDiracDecBin->phHrtfParambin );
1856 : #else
1857 : getDirectPartGains_fx( bin, add( aziDeg, 30 ), eleDeg, &lRealpTmp_fx, &lImagpTmp_fx, &rRealpTmp_fx, &rImagpTmp_fx, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat_fx, &gainCache[gainCacheBaseIndex + 1], isHeadtracked );
1858 : #endif
1859 :
1860 2138881 : hrtfEneSides_fx = L_add( Mpy_32_32( lRealpTmp_fx, lRealpTmp_fx ), // Q25
1861 : L_add( Mpy_32_32( lImagpTmp_fx, lImagpTmp_fx ), // Q25
1862 : L_add( Mpy_32_32( rRealpTmp_fx, rRealpTmp_fx ), // Q25
1863 : Mpy_32_32( rImagpTmp_fx, rImagpTmp_fx ) ) ) ); // Q25
1864 2138881 : lRealp_fx = L_add( lRealp_fx, Mpy_32_32( sidesMul_fx, lRealpTmp_fx ) ); // Q25
1865 2138881 : lImagp_fx = L_add( lImagp_fx, Mpy_32_32( sidesMul_fx, lImagpTmp_fx ) ); // Q25
1866 2138881 : rRealp_fx = L_add( rRealp_fx, Mpy_32_32( sidesMul_fx, rRealpTmp_fx ) ); // Q25
1867 2138881 : rImagp_fx = L_add( rImagp_fx, Mpy_32_32( sidesMul_fx, rImagpTmp_fx ) ); // Q25
1868 :
1869 : /* Apply the gain for the right source of the three coherent sources.
1870 : * -30 degrees to 330 wrapping due to internal functions. */
1871 :
1872 : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
1873 2138881 : getDirectPartGains_fx( bin, aziDeg + 330, eleDeg, &lRealpTmp_fx, &lImagpTmp_fx, &rRealpTmp_fx, &rImagpTmp_fx, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat_fx, &gainCache[gainCacheBaseIndex + 2], isHeadtracked, *hDiracDecBin->phHrtfParambin );
1874 : #else
1875 : getDirectPartGains_fx( bin, aziDeg + 330, eleDeg, &lRealpTmp_fx, &lImagpTmp_fx, &rRealpTmp_fx, &rImagpTmp_fx, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat_fx, &gainCache[gainCacheBaseIndex + 2], isHeadtracked );
1876 : #endif
1877 :
1878 2138881 : hrtfEneSides_fx = L_add( hrtfEneSides_fx,
1879 : L_add( Mpy_32_32( lRealpTmp_fx, lRealpTmp_fx ), // Q25
1880 : L_add( Mpy_32_32( lImagpTmp_fx, lImagpTmp_fx ), // Q25
1881 : L_add( Mpy_32_32( rRealpTmp_fx, rRealpTmp_fx ), // Q25
1882 : Mpy_32_32( rImagpTmp_fx, rImagpTmp_fx ) ) ) ) ); // Q25
1883 2138881 : lRealp_fx = L_add( lRealp_fx, Mpy_32_32( sidesMul_fx, lRealpTmp_fx ) ); // Q25
1884 2138881 : lImagp_fx = L_add( lImagp_fx, Mpy_32_32( sidesMul_fx, lImagpTmp_fx ) ); // Q25
1885 2138881 : rRealp_fx = L_add( rRealp_fx, Mpy_32_32( sidesMul_fx, rRealpTmp_fx ) ); // Q25
1886 2138881 : rImagp_fx = L_add( rImagp_fx, Mpy_32_32( sidesMul_fx, rImagpTmp_fx ) ); // Q25
1887 :
1888 : /* Formulate an eneCorrectionFactor that compensates for the coherent summation of the HRTFs */
1889 2138881 : hrtfEneRealized_fx = L_add( Mpy_32_32( lRealp_fx, lRealp_fx ), // Q19
1890 : L_add( Mpy_32_32( lImagp_fx, lImagp_fx ), // Q19
1891 : L_add( Mpy_32_32( rRealp_fx, rRealp_fx ), // Q19
1892 : Mpy_32_32( rImagp_fx, rImagp_fx ) ) ) ); // Q19
1893 :
1894 2138881 : eneCorrectionFactor_fx = BASOP_Util_Divide3232_Scale( L_add( Mpy_32_32( hrtfEneSides_fx, Mpy_32_32( sidesMul_fx, sidesMul_fx ) ),
1895 : Mpy_32_32( hrtfEneCenter_fx, Mpy_32_32( centerMul_fx, centerMul_fx ) ) ),
1896 : L_max( 1, hrtfEneRealized_fx ), &eneCorrectionFactor_e );
1897 :
1898 : /* Weighting factors to determine appropriate target spectrum for spread coherent sound */
1899 2138881 : IF( LT_16( spreadCoh_fx, 16384 ) )
1900 : {
1901 1639747 : w1_fx = sub( 32767, shl( spreadCoh_fx, 1 ) ); /*Q15*/
1902 1639747 : w2_fx = shl( spreadCoh_fx, 1 ); /*Q15*/
1903 1639747 : w3_fx = 0;
1904 1639747 : move16();
1905 : }
1906 : ELSE
1907 : {
1908 499134 : w1_fx = 0;
1909 499134 : move16();
1910 499134 : w2_fx = shl( sub( 32767, spreadCoh_fx ), 1 ); /*Q15*/
1911 499134 : w3_fx = shl( sub( spreadCoh_fx, 16384 ), 1 ); /*Q15*/
1912 : }
1913 :
1914 2138881 : test();
1915 2138881 : IF( ( EQ_32( ivas_format, MC_FORMAT ) && EQ_32( mc_mode, MC_MODE_MCMASA ) ) )
1916 : {
1917 939257 : idx = s_min( bin, MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS - 1 );
1918 :
1919 : /* Apply the target spectrum to the eneCorrectionFactor */
1920 939257 : IF( separateCenterChannelRendering ) /* spreadCoh mostly originates from phantom sources in separate channel rendering mode */
1921 : {
1922 3514 : eneCorrectionFactor_fx = mult_r( eneCorrectionFactor_fx, add( mult_r( w1_fx, 8192 ), shr( mult_r( add( w2_fx, w3_fx ), spreadCohEne1_fx[idx] ), 1 ) ) );
1923 3514 : eneCorrectionFactor_e = add( eneCorrectionFactor_e, 2 );
1924 : }
1925 : ELSE
1926 : {
1927 935743 : eneCorrectionFactor_fx = mult_r( eneCorrectionFactor_fx, add( mult_r( w1_fx, 4096 ), add( shr( mult_r( w2_fx, spreadCohEne05_fx[idx] ), 1 ), shr( mult_r( w3_fx, spreadCohEne1_fx[idx] ), 2 ) ) ) );
1928 935743 : eneCorrectionFactor_e = add( eneCorrectionFactor_e, 3 );
1929 : }
1930 : }
1931 :
1932 : /* Equalize the spread coherent combined HRTFs */
1933 : Word16 tmp, tmp_e;
1934 2138881 : tmp_e = eneCorrectionFactor_e;
1935 2138881 : move16();
1936 2138881 : tmp = Sqrt16( eneCorrectionFactor_fx, &tmp_e );
1937 2138881 : IF( GE_16( shr( tmp, sub( 15, tmp_e ) ), 4 ) )
1938 : {
1939 2 : eq_fx = 32767; // Q13
1940 2 : move16();
1941 : }
1942 : ELSE
1943 : {
1944 2138879 : eq_fx = shl( tmp, sub( tmp_e, 2 ) ); // Q13
1945 : }
1946 :
1947 2138881 : lRealp_fx = Mpy_32_16_1( lRealp_fx, eq_fx ); // Q23
1948 2138881 : lImagp_fx = Mpy_32_16_1( lImagp_fx, eq_fx ); // Q23
1949 2138881 : rRealp_fx = Mpy_32_16_1( rRealp_fx, eq_fx ); // Q23
1950 2138881 : rImagp_fx = Mpy_32_16_1( rImagp_fx, eq_fx ); // Q23
1951 2138881 : q_lr = Q23;
1952 2138881 : move16();
1953 : }
1954 :
1955 15840427 : hrtfEne_fx[0] = L_add( Mpy_32_32( lRealp_fx, lRealp_fx ), Mpy_32_32( lImagp_fx, lImagp_fx ) ); // Q( 2*q_lr - 31 )
1956 15840427 : hrtfEne_fx[1] = L_add( Mpy_32_32( rRealp_fx, rRealp_fx ), Mpy_32_32( rImagp_fx, rImagp_fx ) ); // Q( 2*q_lr - 31 )
1957 15840427 : move32();
1958 15840427 : move32();
1959 15840427 : hrtfCrossRe_fx = L_add( Mpy_32_32( lRealp_fx, rRealp_fx ), Mpy_32_32( lImagp_fx, rImagp_fx ) ); // Q( 2*q_lr - 31 )
1960 15840427 : hrtfCrossIm_fx = L_add( Mpy_32_32( -lImagp_fx, rRealp_fx ), Mpy_32_32( lRealp_fx, rImagp_fx ) ); // Q( 2*q_lr - 31 )
1961 :
1962 : /* Add direct part (1 or 2) covariance matrix */
1963 15840427 : dirEne_fx = Mpy_32_32( ratio_fx, meanEnePerCh_fx ); // Q(q_meanEnePerCh - 1)
1964 15840427 : shift = norm_l( dirEne_fx );
1965 15840427 : dirEne_fx = L_shl( dirEne_fx, shift );
1966 15840427 : q_dirEne = add( sub( q_meanEnePerCh, 1 ), shift );
1967 :
1968 15840427 : hDiracDecBin->ChEneOut_fx[0][bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEneOut_fx[0][bin], hDiracDecBin->ChEneOut_e[0][bin], Mpy_32_32( dirEne_fx, hrtfEne_fx[0] ), sub( 31, sub( add( q_dirEne, shl( q_lr, 1 ) ), 62 ) ), &hDiracDecBin->ChEneOut_e[0][bin] ); /* Dir ene part*/
1969 15840427 : hDiracDecBin->ChEneOut_fx[1][bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEneOut_fx[1][bin], hDiracDecBin->ChEneOut_e[1][bin], Mpy_32_32( dirEne_fx, hrtfEne_fx[1] ), sub( 31, sub( add( q_dirEne, shl( q_lr, 1 ) ), 62 ) ), &hDiracDecBin->ChEneOut_e[1][bin] );
1970 15840427 : hDiracDecBin->ChCrossReOut_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossReOut_fx[bin], hDiracDecBin->ChCrossReOut_e[bin], Mpy_32_32( dirEne_fx, hrtfCrossRe_fx ), sub( 31, sub( add( q_dirEne, shl( q_lr, 1 ) ), 62 ) ), &hDiracDecBin->ChCrossReOut_e[bin] ); /* Dir cross re */
1971 15840427 : hDiracDecBin->ChCrossImOut_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossImOut_fx[bin], hDiracDecBin->ChCrossImOut_e[bin], Mpy_32_32( dirEne_fx, hrtfCrossIm_fx ), sub( 31, sub( add( q_dirEne, shl( q_lr, 1 ) ), 62 ) ), &hDiracDecBin->ChCrossImOut_e[bin] ); /* Dir cross im */
1972 15840427 : move32();
1973 15840427 : move32();
1974 15840427 : move32();
1975 15840427 : move32();
1976 : }
1977 :
1978 : /* Add diffuse / ambient part covariance matrix */
1979 13918420 : diffuseness_fx = L_max( 0, diffuseness_fx ); // Q30
1980 13918420 : diffEne_fx = Mpy_32_32( diffuseness_fx, meanEnePerCh_fx ); // Q(2q - 32)
1981 13918420 : shift = norm_l( diffEne_fx );
1982 13918420 : diffEne_fx = L_shl( diffEne_fx, shift );
1983 13918420 : q_diffEne = add( shift, sub( q_meanEnePerCh, 1 ) );
1984 :
1985 13918420 : surCoh_fx = hSpatParamRendCom->surroundingCoherence_fx[dirac_read_idx][bin]; // Q15
1986 13918420 : move16();
1987 :
1988 13918420 : diffusenessValForDecorrelationReduction_fx = L_max( 0, diffusenessValForDecorrelationReduction_fx ); // Q30
1989 13918420 : diffEneValForDecorrelationReduction_fx = Mpy_32_32( diffusenessValForDecorrelationReduction_fx, meanEnePerCh_fx ); // resulting Q = q_meanEnePerCh - 1
1990 13918420 : q_diffEneValForDecorrelationReduction = sub( q_meanEnePerCh, 1 );
1991 :
1992 13918420 : test();
1993 13918420 : IF( ( EQ_32( ivas_format, MC_FORMAT ) && EQ_32( mc_mode, MC_MODE_MCMASA ) ) )
1994 : {
1995 1640240 : IF( !hDiracDecBin->renderStereoOutputInsteadOfBinaural )
1996 : {
1997 : Word32 spectrumModVal;
1998 :
1999 1640240 : idx = s_min( bin, MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS - 1 );
2000 : /* Apply target spectrum that emphasizes low frequencies when the sound is surround coherent */
2001 1640240 : spectrumModVal = L_add( L_sub( ONE_IN_Q29, L_shl( surCoh_fx, 14 ) ), L_mult( surCoh_fx, surCohEne_fx[idx] ) ); // Q29
2002 1640240 : diffEne_fx = Mpy_32_32( diffEne_fx, spectrumModVal ); // Q-2
2003 1640240 : q_diffEne = sub( q_diffEne, 2 );
2004 : /* Modify also the value for decorrelation reduction */
2005 1640240 : diffEneValForDecorrelationReduction_fx = Mpy_32_32( diffEneValForDecorrelationReduction_fx, spectrumModVal ); // Q-2
2006 1640240 : q_diffEneValForDecorrelationReduction = sub( q_diffEneValForDecorrelationReduction, 2 );
2007 : }
2008 : }
2009 13918420 : hDiracDecBin->ChEneOut_fx[0][bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEneOut_fx[0][bin], hDiracDecBin->ChEneOut_e[0][bin], diffEne_fx, sub( 31, q_diffEne ), &hDiracDecBin->ChEneOut_e[0][bin] ); /* Diff ene part*/
2010 13918420 : hDiracDecBin->ChEneOut_fx[1][bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEneOut_fx[1][bin], hDiracDecBin->ChEneOut_e[1][bin], diffEne_fx, sub( 31, q_diffEne ), &hDiracDecBin->ChEneOut_e[1][bin] );
2011 :
2012 13918420 : move32();
2013 13918420 : move32();
2014 13918420 : IF( hDiracDecBin->renderStereoOutputInsteadOfBinaural )
2015 : {
2016 : /* When rendering stereo, ambience (except for surround coherent sound) has zero ICC. */
2017 1032140 : hDiracDecBin->ChCrossReOut_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossReOut_fx[bin], hDiracDecBin->ChCrossReOut_e[bin], Mpy_32_16_1( diffEne_fx, surCoh_fx ), sub( 31, q_diffEne ), &hDiracDecBin->ChCrossReOut_e[bin] );
2018 1032140 : move32();
2019 : }
2020 : ELSE /* When rendering binaural, ambience has frequency dependent ICC. */
2021 : {
2022 12886280 : test();
2023 12886280 : test();
2024 12886280 : IF( ( EQ_32( ivas_format, SBA_FORMAT ) || EQ_32( ivas_format, SBA_ISM_FORMAT ) ) && LT_16( bin, BINAURAL_COHERENCE_DIFFERENCE_BINS ) )
2025 1356912 : {
2026 : Word32 diffuseFieldCoherence_fx;
2027 : Word16 tmp_exp;
2028 1356912 : temp = BASOP_Util_Add_Mant32Exp( Mpy_32_32( hDiracDecBin->hDiffuseDist->diffuseRatioX_fx[bin], hDiracDecBin->diffuseFieldCoherenceX_fx[bin] ), 0, Mpy_32_32( hDiracDecBin->hDiffuseDist->diffuseRatioY_fx[bin], hDiracDecBin->diffuseFieldCoherenceY_fx[bin] ), 0, &tmp_exp );
2029 1356912 : diffuseFieldCoherence_fx = BASOP_Util_Add_Mant32Exp( temp, tmp_exp, Mpy_32_32( hDiracDecBin->hDiffuseDist->diffuseRatioZ_fx[bin], hDiracDecBin->diffuseFieldCoherenceZ_fx[bin] ), 0, &tmp_exp );
2030 1356912 : temp = BASOP_Util_Add_Mant32Exp( Mpy_32_16_1( diffuseFieldCoherence_fx, sub( 32767, surCoh_fx ) ), tmp_exp, L_shl( surCoh_fx, 16 ), 0, &tmp_exp );
2031 1356912 : hDiracDecBin->ChCrossReOut_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossReOut_fx[bin], hDiracDecBin->ChCrossReOut_e[bin], Mpy_32_32( temp, diffEne_fx ), add( tmp_exp, sub( 31, q_diffEne ) ), &hDiracDecBin->ChCrossReOut_e[bin] );
2032 : }
2033 : ELSE
2034 : {
2035 11529368 : hDiracDecBin->ChCrossReOut_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossReOut_fx[bin], hDiracDecBin->ChCrossReOut_e[bin], Mpy_32_32( L_add( Mpy_32_16_1( hDiracDecBin->diffuseFieldCoherence_fx[bin], sub( 32767, surCoh_fx ) ), L_shl( surCoh_fx, 16 ) ), diffEne_fx ), sub( 31, q_diffEne ), &hDiracDecBin->ChCrossReOut_e[bin] );
2036 : }
2037 12886280 : move32();
2038 : }
2039 :
2040 : /* Store parameters for formulating average diffuseness over frame */
2041 13918420 : Word32 frameMeanDiffuseness = BASOP_Util_Add_Mant32Exp( hDiracDecBin->frameMeanDiffuseness_fx[bin], 2 /*Q29*/, diffEneValForDecorrelationReduction_fx, sub( 31, q_diffEneValForDecorrelationReduction ), &exp1 ); // exp = exp1
2042 13918420 : frameMeanDiffusenessEneWeight_fx[bin] = L_add( frameMeanDiffusenessEneWeight_fx[bin], meanEnePerCh_fx );
2043 13918420 : move32();
2044 :
2045 : /* Formulate average diffuseness over frame */
2046 13918420 : frameMeanDiffuseness = BASOP_Util_Divide3232_Scale_cadence( frameMeanDiffuseness, L_max( EPSILLON_FX, frameMeanDiffusenessEneWeight_fx[bin] ), &exp ); // exp = exp + 31 - q_meanEnePerCh - exp1
2047 13918420 : exp = sub( exp, sub( sub( 31, q_meanEnePerCh ), exp1 ) );
2048 13918420 : hDiracDecBin->frameMeanDiffuseness_fx[bin] = L_shl( frameMeanDiffuseness, sub( exp, 2 ) ); // Q29
2049 13918420 : move32();
2050 : }
2051 :
2052 14200945 : FOR( bin = 0; bin < nBins; bin++ )
2053 : {
2054 13918420 : hDiracDecBin->ChCrossReOut_fx[bin] = Mpy_32_32( hDiracDecBin->ChCrossReOut_fx[bin], qualityBasedSmFactor_fx );
2055 13918420 : hDiracDecBin->ChCrossImOut_fx[bin] = Mpy_32_32( hDiracDecBin->ChCrossImOut_fx[bin], qualityBasedSmFactor_fx );
2056 :
2057 41755260 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
2058 : {
2059 27836840 : hDiracDecBin->ChEneOut_fx[ch][bin] = Mpy_32_32( hDiracDecBin->ChEneOut_fx[ch][bin], qualityBasedSmFactor_fx );
2060 27836840 : move32();
2061 : }
2062 13918420 : hDiracDecBin->ChCrossReOut_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossReOut_fx[bin], hDiracDecBin->ChCrossReOut_e[bin], Mpy_32_32( hDiracDecBin->ChCrossReOutPrev_fx[bin], IIReneLimiter_fx[bin] ), hDiracDecBin->ChCrossReOutPrev_e[bin], &hDiracDecBin->ChCrossReOut_e[bin] );
2063 13918420 : hDiracDecBin->ChCrossImOut_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossImOut_fx[bin], hDiracDecBin->ChCrossImOut_e[bin], Mpy_32_32( hDiracDecBin->ChCrossImOutPrev_fx[bin], IIReneLimiter_fx[bin] ), hDiracDecBin->ChCrossImOutPrev_e[bin], &hDiracDecBin->ChCrossImOut_e[bin] );
2064 13918420 : move32();
2065 13918420 : move32();
2066 :
2067 41755260 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
2068 : {
2069 27836840 : hDiracDecBin->ChEneOut_fx[ch][bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEneOut_fx[ch][bin], hDiracDecBin->ChEneOut_e[ch][bin], Mpy_32_32( hDiracDecBin->ChEneOutPrev_fx[ch][bin], IIReneLimiter_fx[bin] ), hDiracDecBin->ChEneOutPrev_e[ch][bin], &hDiracDecBin->ChEneOut_e[ch][bin] );
2070 27836840 : move32();
2071 : }
2072 :
2073 :
2074 13918420 : hDiracDecBin->ChCrossReOutPrev_fx[bin] = hDiracDecBin->ChCrossReOut_fx[bin];
2075 13918420 : move32();
2076 13918420 : hDiracDecBin->ChCrossImOutPrev_fx[bin] = hDiracDecBin->ChCrossImOut_fx[bin];
2077 13918420 : move32();
2078 13918420 : hDiracDecBin->ChCrossReOutPrev_e[bin] = hDiracDecBin->ChCrossReOut_e[bin];
2079 13918420 : move16();
2080 13918420 : hDiracDecBin->ChCrossImOutPrev_e[bin] = hDiracDecBin->ChCrossImOut_e[bin];
2081 13918420 : move16();
2082 :
2083 41755260 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
2084 : {
2085 27836840 : hDiracDecBin->ChEnePrev_fx[ch][bin] = hDiracDecBin->ChEne_fx[ch][bin];
2086 27836840 : move32();
2087 27836840 : hDiracDecBin->ChEnePrev_e[ch][bin] = hDiracDecBin->ChEne_e[ch][bin];
2088 27836840 : move16();
2089 27836840 : hDiracDecBin->ChEneOutPrev_fx[ch][bin] = hDiracDecBin->ChEneOut_fx[ch][bin];
2090 27836840 : move32();
2091 27836840 : hDiracDecBin->ChEneOutPrev_e[ch][bin] = hDiracDecBin->ChEneOut_e[ch][bin];
2092 27836840 : move16();
2093 : }
2094 : }
2095 :
2096 282525 : return;
2097 : }
2098 :
2099 :
2100 282525 : static void ivas_dirac_dec_binaural_determine_processing_matrices_fx(
2101 : DIRAC_DEC_BIN_HANDLE hDiracDecBin,
2102 : SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom,
2103 : PARAMBIN_REND_CONFIG_HANDLE hConfig,
2104 : const Word16 max_band_decorr,
2105 : Word32 Rmat[3][3], /*Q30*/
2106 : const Word16 subframe,
2107 : const Word16 isHeadtracked,
2108 : const Word16 nchanSeparateChannels,
2109 : const MASA_ISM_DATA_HANDLE hMasaIsmData )
2110 : {
2111 : Word16 chA, chB, bin;
2112 : Word16 separateCenterChannelRendering;
2113 : Word16 nBins;
2114 : Word16 dirac_read_idx;
2115 : PARAMBIN_HRTF_GAIN_CACHE gainCache[MAX_NUM_OBJECTS];
2116 : Word16 idx;
2117 : ISM_MODE ism_mode;
2118 : IVAS_FORMAT ivas_format;
2119 : MC_MODE mc_mode;
2120 : Word32 ivas_total_brate;
2121 : Word16 nchan_transport;
2122 : Word16 exp;
2123 : Word16 q_processMtx[CLDFB_NO_CHANNELS_MAX], q_processMtxPrev[CLDFB_NO_CHANNELS_MAX];
2124 : Word16 q_processMtx_SCCR[CLDFB_NO_CHANNELS_MAX], q_processMtxPrev_SCCR[CLDFB_NO_CHANNELS_MAX];
2125 : Word16 q_processMtxDec[CLDFB_NO_CHANNELS_MAX], q_processMtxDecPrev[CLDFB_NO_CHANNELS_MAX];
2126 282525 : set16_fx( q_processMtx, hDiracDecBin->q_processMtx, CLDFB_NO_CHANNELS_MAX );
2127 282525 : set16_fx( q_processMtxPrev, hDiracDecBin->q_processMtxPrev, CLDFB_NO_CHANNELS_MAX );
2128 282525 : set16_fx( q_processMtx_SCCR, hDiracDecBin->q_processMtx, CLDFB_NO_CHANNELS_MAX );
2129 282525 : set16_fx( q_processMtxPrev_SCCR, hDiracDecBin->q_processMtxPrev, CLDFB_NO_CHANNELS_MAX );
2130 282525 : set16_fx( q_processMtxDec, hDiracDecBin->q_processMtxDec, CLDFB_NO_CHANNELS_MAX );
2131 282525 : set16_fx( q_processMtxDecPrev, hDiracDecBin->q_processMtxDecPrev, CLDFB_NO_CHANNELS_MAX );
2132 :
2133 282525 : ivas_format = hConfig->ivas_format;
2134 282525 : move32();
2135 282525 : separateCenterChannelRendering = extract_l( GT_16( nchanSeparateChannels, 0 ) );
2136 282525 : move16();
2137 282525 : mc_mode = hConfig->mc_mode;
2138 282525 : move32();
2139 282525 : ivas_total_brate = hConfig->ivas_total_brate;
2140 282525 : move32();
2141 282525 : nchan_transport = hConfig->nchan_transport;
2142 282525 : move16();
2143 282525 : nBins = hSpatParamRendCom->num_freq_bands; /* Actually bins */
2144 282525 : move16();
2145 :
2146 282525 : ism_mode = hConfig->ism_mode;
2147 282525 : move32();
2148 :
2149 282525 : dirac_read_idx = hSpatParamRendCom->render_to_md_map[subframe];
2150 282525 : move16();
2151 :
2152 1412625 : FOR( idx = 0; idx < MAX_NUM_OBJECTS; idx++ )
2153 : {
2154 1130100 : gainCache[idx].azi = -1000; /* Use -1000 as value for uninitialized cache. */
2155 1130100 : move16();
2156 : }
2157 :
2158 14200945 : FOR( bin = 0; bin < nBins; bin++ )
2159 : {
2160 : Word32 tmpMtxRe_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], tmpMtxIm_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], resultMtxRe_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], resultMtxIm_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], gain_fx;
2161 : Word32 CxRe_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], CxIm_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; /* Input covariance matrix */
2162 : Word32 realizedOutputEne_fx, targetOutputEne_fx, missingOutputEne_fx;
2163 : Word32 CrEneL_fx, CrEneR_fx; /* Cr = residual decorrelated sound covariance matrix */
2164 : Word32 CrCrossRe_fx, CrCrossIm_fx;
2165 : Word32 Mre_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Mim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], MdecRe_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], MdecIm_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; /* M = mixing matrix; Mdec = residual decorrelated signal mixing matrix */
2166 13918420 : Word32 prototypeMtx_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS] = { { ONE_IN_Q31, 107374182 }, { 107374182, ONE_IN_Q31 } };
2167 13918420 : move32();
2168 13918420 : Word16 q_M, q_Cx, q_tmp, q_res, q_CrEne, q_CrCross, q_Mdec = 0;
2169 13918420 : move16();
2170 : Word32 tmp1, tmp2, res1, res2;
2171 : Word16 q_tmp1, q_tmp2, q_realizedOutputEne, q_targetOutputEne, q_missingOutputEne, q_gain;
2172 : Word16 exp1, exp2, q_processMtx_bin, q_processMtxDec_bin;
2173 :
2174 13918420 : CrEneL_fx = 0;
2175 13918420 : move32();
2176 13918420 : CrEneR_fx = 0;
2177 13918420 : move32();
2178 13918420 : q_CrEne = Q31;
2179 13918420 : move16();
2180 :
2181 13918420 : Word16 q_diff = sub( hDiracDecBin->ChEne_e[0][bin], hDiracDecBin->ChEne_e[1][bin] );
2182 :
2183 13918420 : IF( q_diff > 0 )
2184 : {
2185 1927092 : hDiracDecBin->ChEne_fx[1][bin] = L_shr( hDiracDecBin->ChEne_fx[1][bin], q_diff );
2186 1927092 : hDiracDecBin->q_ChEne = sub( 31, hDiracDecBin->ChEne_e[0][bin] );
2187 1927092 : hDiracDecBin->ChEne_e[1][bin] = hDiracDecBin->ChEne_e[0][bin];
2188 : }
2189 : ELSE
2190 : {
2191 11991328 : hDiracDecBin->ChEne_fx[0][bin] = L_shl( hDiracDecBin->ChEne_fx[0][bin], q_diff );
2192 11991328 : hDiracDecBin->q_ChEne = sub( 31, hDiracDecBin->ChEne_e[1][bin] );
2193 11991328 : hDiracDecBin->ChEne_e[0][bin] = hDiracDecBin->ChEne_e[1][bin];
2194 : }
2195 13918420 : move32();
2196 13918420 : move16();
2197 13918420 : move16();
2198 :
2199 13918420 : q_diff = sub( hDiracDecBin->ChEneOut_e[0][bin], hDiracDecBin->ChEneOut_e[1][bin] );
2200 13918420 : IF( q_diff > 0 )
2201 : {
2202 3069343 : hDiracDecBin->ChEneOut_fx[1][bin] = L_shr( hDiracDecBin->ChEneOut_fx[1][bin], q_diff );
2203 3069343 : hDiracDecBin->q_ChEneOut = sub( 31, hDiracDecBin->ChEneOut_e[0][bin] );
2204 3069343 : hDiracDecBin->ChEneOut_e[1][bin] = hDiracDecBin->ChEneOut_e[0][bin];
2205 : }
2206 : ELSE
2207 : {
2208 10849077 : hDiracDecBin->ChEneOut_fx[0][bin] = L_shl( hDiracDecBin->ChEneOut_fx[0][bin], q_diff );
2209 10849077 : hDiracDecBin->q_ChEneOut = sub( 31, hDiracDecBin->ChEneOut_e[1][bin] );
2210 10849077 : hDiracDecBin->ChEneOut_e[0][bin] = hDiracDecBin->ChEneOut_e[1][bin];
2211 : }
2212 13918420 : move32();
2213 13918420 : move16();
2214 13918420 : move16();
2215 :
2216 13918420 : q_diff = sub( hDiracDecBin->ChCrossRe_e[bin], hDiracDecBin->ChCrossIm_e[bin] );
2217 13918420 : IF( q_diff > 0 )
2218 : {
2219 11789098 : hDiracDecBin->ChCrossIm_fx[bin] = L_shr( hDiracDecBin->ChCrossIm_fx[bin], q_diff );
2220 11789098 : hDiracDecBin->q_ChCross = sub( 31, hDiracDecBin->ChCrossRe_e[bin] );
2221 11789098 : hDiracDecBin->ChCrossIm_e[bin] = hDiracDecBin->ChCrossRe_e[bin];
2222 : }
2223 : ELSE
2224 : {
2225 2129322 : hDiracDecBin->ChCrossRe_fx[bin] = L_shl( hDiracDecBin->ChCrossRe_fx[bin], q_diff );
2226 2129322 : hDiracDecBin->q_ChCross = sub( 31, hDiracDecBin->ChCrossIm_e[bin] );
2227 2129322 : hDiracDecBin->ChCrossRe_e[bin] = hDiracDecBin->ChCrossIm_e[bin];
2228 : }
2229 13918420 : move32();
2230 13918420 : move16();
2231 13918420 : move16();
2232 :
2233 13918420 : q_diff = sub( hDiracDecBin->ChCrossReOut_e[bin], hDiracDecBin->ChCrossImOut_e[bin] );
2234 13918420 : IF( q_diff > 0 )
2235 : {
2236 12489847 : hDiracDecBin->ChCrossImOut_fx[bin] = L_shr( hDiracDecBin->ChCrossImOut_fx[bin], q_diff );
2237 12489847 : hDiracDecBin->q_ChCrossOut = sub( 31, hDiracDecBin->ChCrossReOut_e[bin] );
2238 12489847 : hDiracDecBin->ChCrossImOut_e[bin] = hDiracDecBin->ChCrossReOut_e[bin];
2239 : }
2240 : ELSE
2241 : {
2242 1428573 : hDiracDecBin->ChCrossReOut_fx[bin] = L_shl( hDiracDecBin->ChCrossReOut_fx[bin], q_diff );
2243 1428573 : hDiracDecBin->q_ChCrossOut = sub( 31, hDiracDecBin->ChCrossImOut_e[bin] );
2244 1428573 : hDiracDecBin->ChCrossReOut_e[bin] = hDiracDecBin->ChCrossImOut_e[bin];
2245 : }
2246 13918420 : move32();
2247 13918420 : move16();
2248 13918420 : move16();
2249 :
2250 13918420 : formulate2x2MixingMatrix_fx( hDiracDecBin->ChEne_fx[0][bin], hDiracDecBin->ChEne_fx[1][bin],
2251 13918420 : hDiracDecBin->q_ChEne,
2252 : hDiracDecBin->ChCrossRe_fx[bin], hDiracDecBin->ChCrossIm_fx[bin],
2253 13918420 : hDiracDecBin->q_ChCross,
2254 : hDiracDecBin->ChEneOut_fx[0][bin], hDiracDecBin->ChEneOut_fx[1][bin],
2255 13918420 : hDiracDecBin->q_ChEneOut,
2256 : hDiracDecBin->ChCrossReOut_fx[bin], hDiracDecBin->ChCrossImOut_fx[bin],
2257 13918420 : hDiracDecBin->q_ChCrossOut,
2258 13918420 : prototypeMtx_fx, Mre_fx, Mim_fx, &q_M, hDiracDecBin->reqularizationFactor_fx );
2259 :
2260 13918420 : IF( LT_16( hDiracDecBin->q_ChEne, hDiracDecBin->q_ChCross ) )
2261 : {
2262 7950629 : CxRe_fx[0][0] = hDiracDecBin->ChEne_fx[0][bin];
2263 7950629 : move32();
2264 7950629 : CxRe_fx[1][1] = hDiracDecBin->ChEne_fx[1][bin];
2265 7950629 : move32();
2266 7950629 : CxRe_fx[1][0] = L_shr( hDiracDecBin->ChCrossRe_fx[bin], sub( hDiracDecBin->q_ChCross, hDiracDecBin->q_ChEne ) );
2267 7950629 : move32();
2268 7950629 : CxRe_fx[0][1] = L_shr( hDiracDecBin->ChCrossRe_fx[bin], sub( hDiracDecBin->q_ChCross, hDiracDecBin->q_ChEne ) );
2269 7950629 : move32();
2270 7950629 : CxIm_fx[0][0] = 0;
2271 7950629 : move32();
2272 7950629 : CxIm_fx[1][1] = 0;
2273 7950629 : move32();
2274 7950629 : CxIm_fx[1][0] = L_shr( hDiracDecBin->ChCrossIm_fx[bin], sub( hDiracDecBin->q_ChCross, hDiracDecBin->q_ChEne ) );
2275 7950629 : move32();
2276 7950629 : CxIm_fx[0][1] = L_shr( L_negate( hDiracDecBin->ChCrossIm_fx[bin] ), sub( hDiracDecBin->q_ChCross, hDiracDecBin->q_ChEne ) );
2277 7950629 : move32();
2278 7950629 : q_Cx = hDiracDecBin->q_ChEne;
2279 7950629 : move16();
2280 : }
2281 : ELSE
2282 : {
2283 5967791 : CxRe_fx[0][0] = L_shr( hDiracDecBin->ChEne_fx[0][bin], sub( hDiracDecBin->q_ChEne, hDiracDecBin->q_ChCross ) );
2284 5967791 : move32();
2285 5967791 : CxRe_fx[1][1] = L_shr( hDiracDecBin->ChEne_fx[1][bin], sub( hDiracDecBin->q_ChEne, hDiracDecBin->q_ChCross ) );
2286 5967791 : move32();
2287 5967791 : CxRe_fx[1][0] = hDiracDecBin->ChCrossRe_fx[bin];
2288 5967791 : move32();
2289 5967791 : CxRe_fx[0][1] = hDiracDecBin->ChCrossRe_fx[bin];
2290 5967791 : move32();
2291 5967791 : CxIm_fx[0][0] = 0;
2292 5967791 : move32();
2293 5967791 : CxIm_fx[1][1] = 0;
2294 5967791 : move32();
2295 5967791 : CxIm_fx[1][0] = hDiracDecBin->ChCrossIm_fx[bin];
2296 5967791 : move32();
2297 5967791 : CxIm_fx[0][1] = L_negate( hDiracDecBin->ChCrossIm_fx[bin] );
2298 5967791 : move32();
2299 5967791 : q_Cx = hDiracDecBin->q_ChCross;
2300 5967791 : move16();
2301 : }
2302 :
2303 : /* Make matrix multiplication M*Cx*M' to determine resulting covariance matrix of processing input with M */
2304 13918420 : matrixMul_fx( Mre_fx, Mim_fx, &q_M, CxRe_fx, CxIm_fx, &q_Cx, tmpMtxRe_fx, tmpMtxIm_fx, &q_tmp );
2305 13918420 : matrixTransp2Mul_fx(
2306 : tmpMtxRe_fx, tmpMtxIm_fx, &q_tmp, Mre_fx, Mim_fx, &q_M,
2307 : 1 /*int Ascale*/,
2308 : 0 /*int Bscale*/,
2309 : resultMtxRe_fx, resultMtxIm_fx, &q_res );
2310 :
2311 : /* When below the frequency limit where decorrelation is applied, we inject the decorrelated
2312 : * residual (or missing) signal component. The procedure is active when there are not enough independent
2313 : * signal energy to synthesize a signal with the target covariance matrix from the non-decorrelated signals */
2314 13918420 : IF( LT_16( bin, max_band_decorr ) )
2315 : {
2316 : Word32 decorrelationReductionFactor_fx;
2317 : Word16 q_decorrelationReductionFactor;
2318 :
2319 : /* Subtract the resulting covariance matrix from the target covariance matrix to determine
2320 : * what signal component is missing. The result is the target covariance matrix for the residual signal, i.e.,
2321 : * a residual covariance matrix. */
2322 7496145 : exp = sub( get_min_scalefactor( hDiracDecBin->ChEneOut_fx[0][bin], hDiracDecBin->ChEneOut_fx[1][bin] ), 3 );
2323 7496145 : tmp1 = L_shl( hDiracDecBin->ChEneOut_fx[0][bin], exp );
2324 7496145 : tmp2 = L_shl( hDiracDecBin->ChEneOut_fx[1][bin], exp );
2325 7496145 : q_tmp1 = add( hDiracDecBin->q_ChEneOut, exp );
2326 :
2327 7496145 : exp = sub( get_min_scalefactor( resultMtxRe_fx[0][0], resultMtxRe_fx[1][1] ), 3 );
2328 7496145 : res1 = L_shl( resultMtxRe_fx[0][0], exp );
2329 7496145 : res2 = L_shl( resultMtxRe_fx[1][1], exp );
2330 7496145 : q_tmp2 = add( q_res, exp );
2331 :
2332 7496145 : IF( LT_16( q_tmp1, q_tmp2 ) )
2333 : {
2334 2490006 : CrEneL_fx = L_max( 0, L_sub( tmp1, L_shr( res1, sub( q_tmp2, q_tmp1 ) ) ) );
2335 2490006 : CrEneR_fx = L_max( 0, L_sub( tmp2, L_shr( res2, sub( q_tmp2, q_tmp1 ) ) ) );
2336 2490006 : q_CrEne = q_tmp1;
2337 2490006 : move16();
2338 : }
2339 : ELSE
2340 : {
2341 5006139 : CrEneL_fx = L_max( 0, L_sub( L_shr( tmp1, sub( q_tmp1, q_tmp2 ) ), res1 ) );
2342 5006139 : CrEneR_fx = L_max( 0, L_sub( L_shr( tmp2, sub( q_tmp1, q_tmp2 ) ), res2 ) );
2343 5006139 : q_CrEne = q_tmp2;
2344 5006139 : move16();
2345 : }
2346 :
2347 7496145 : exp = sub( get_min_scalefactor( hDiracDecBin->ChCrossReOut_fx[bin], hDiracDecBin->ChCrossImOut_fx[bin] ), 3 );
2348 7496145 : tmp1 = L_shl( hDiracDecBin->ChCrossReOut_fx[bin], exp );
2349 7496145 : tmp2 = L_shl( hDiracDecBin->ChCrossImOut_fx[bin], exp );
2350 7496145 : q_tmp1 = add( hDiracDecBin->q_ChCrossOut, exp );
2351 :
2352 7496145 : exp = sub( get_min_scalefactor( resultMtxRe_fx[1][0], resultMtxIm_fx[1][0] ), 3 );
2353 7496145 : res1 = L_shl( resultMtxRe_fx[1][0], exp );
2354 7496145 : res2 = L_shl( resultMtxIm_fx[1][0], exp );
2355 7496145 : q_tmp2 = add( q_res, exp );
2356 :
2357 7496145 : IF( LT_16( q_tmp1, q_tmp2 ) )
2358 : {
2359 218220 : CrCrossRe_fx = L_sub( tmp1, L_shr( res1, sub( q_tmp2, q_tmp1 ) ) );
2360 218220 : CrCrossIm_fx = L_sub( tmp2, L_shr( res2, sub( q_tmp2, q_tmp1 ) ) );
2361 218220 : q_CrCross = q_tmp1;
2362 218220 : move16();
2363 : }
2364 : ELSE
2365 : {
2366 7277925 : CrCrossRe_fx = L_sub( L_shr( tmp1, sub( q_tmp1, q_tmp2 ) ), res1 );
2367 7277925 : CrCrossIm_fx = L_sub( L_shr( tmp2, sub( q_tmp1, q_tmp2 ) ), res2 );
2368 7277925 : q_CrCross = q_tmp2;
2369 7277925 : move16();
2370 : }
2371 :
2372 : /* The amount of the decorrelated sound is further controlled based on the spatial metadata,
2373 : * by determining an energy-suppressed residual covariance matrix that is a control parameter
2374 : * that guides the processing of the decorrelated sound to a residual signal.
2375 : * The procedure improves quality in e.g. double-talk 2-direction rendering situations.*/
2376 7496145 : test();
2377 7496145 : IF( EQ_16( ivas_format, MASA_FORMAT ) && LT_32( ivas_total_brate, MASA_STEREO_MIN_BITRATE ) )
2378 : {
2379 515460 : decorrelationReductionFactor_fx = ONE_IN_Q30;
2380 515460 : move32();
2381 515460 : q_decorrelationReductionFactor = Q30;
2382 515460 : move16();
2383 : }
2384 6980685 : ELSE IF( L_or( L_and( EQ_16( ivas_format, MC_FORMAT ), EQ_16( mc_mode, MC_MODE_MCMASA ) ), L_and( EQ_16( ivas_format, MASA_FORMAT ), EQ_16( nchan_transport, 1 ) ) ) )
2385 : {
2386 2322965 : exp = 31 - 29;
2387 2322965 : move16();
2388 2322965 : decorrelationReductionFactor_fx = Sqrt32( L_max( 0, hDiracDecBin->frameMeanDiffuseness_fx[bin] ), &exp );
2389 2322965 : q_decorrelationReductionFactor = sub( 31, exp );
2390 : }
2391 4657720 : ELSE IF( L_and( L_or( EQ_16( ivas_format, SBA_FORMAT ), EQ_16( ivas_format, SBA_ISM_FORMAT ) ), EQ_16( nchan_transport, 1 ) ) )
2392 : {
2393 2823640 : decorrelationReductionFactor_fx = ONE_IN_Q30;
2394 2823640 : move32();
2395 2823640 : q_decorrelationReductionFactor = Q30;
2396 2823640 : move16();
2397 : }
2398 : ELSE
2399 : {
2400 1834080 : decorrelationReductionFactor_fx = L_max( 0, hDiracDecBin->frameMeanDiffuseness_fx[bin] );
2401 1834080 : q_decorrelationReductionFactor = 29;
2402 1834080 : move16();
2403 : }
2404 :
2405 7496145 : CrEneL_fx = Mpy_32_32( CrEneL_fx, decorrelationReductionFactor_fx );
2406 7496145 : CrEneR_fx = Mpy_32_32( CrEneR_fx, decorrelationReductionFactor_fx );
2407 7496145 : q_CrEne = sub( add( q_CrEne, q_decorrelationReductionFactor ), 31 );
2408 7496145 : CrCrossRe_fx = Mpy_32_32( CrCrossRe_fx, decorrelationReductionFactor_fx );
2409 7496145 : CrCrossIm_fx = Mpy_32_32( CrCrossIm_fx, decorrelationReductionFactor_fx );
2410 7496145 : q_CrCross = sub( add( q_CrCross, q_decorrelationReductionFactor ), 31 );
2411 :
2412 7496145 : formulate2x2MixingMatrix_fx( hDiracDecBin->ChEne_fx[0][bin], hDiracDecBin->ChEne_fx[1][bin],
2413 7496145 : hDiracDecBin->q_ChEne,
2414 : 0, 0, /* Decorrelated signal has ideally no cross-terms */
2415 : Q31, CrEneL_fx, CrEneR_fx, q_CrEne,
2416 : CrCrossRe_fx, CrCrossIm_fx, q_CrCross,
2417 : prototypeMtx_fx, MdecRe_fx, MdecIm_fx, &q_Mdec, 3277 ); // 3277 = 0.2 in Q14
2418 : }
2419 : ELSE
2420 : {
2421 19266825 : FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
2422 : {
2423 12844550 : set_zero_fx( MdecRe_fx[chA], BINAURAL_CHANNELS );
2424 12844550 : set_zero_fx( MdecIm_fx[chA], BINAURAL_CHANNELS );
2425 : }
2426 6422275 : q_Mdec = Q31;
2427 6422275 : move16();
2428 : }
2429 :
2430 : /* The regularizations at determining mixing matrices cause signal energy to be lost to some degree, which is compensated for here */
2431 13918420 : tmp1 = L_add( CrEneL_fx, CrEneR_fx );
2432 13918420 : exp = sub( get_min_scalefactor( resultMtxRe_fx[0][0], resultMtxRe_fx[1][1] ), 2 );
2433 13918420 : tmp2 = L_add( L_shl( resultMtxRe_fx[0][0], exp ), L_shl( resultMtxRe_fx[1][1], exp ) );
2434 13918420 : q_tmp2 = add( q_res, exp );
2435 :
2436 : /*Limiting value to Q63*/
2437 13918420 : IF( GT_16( q_tmp2, 63 ) )
2438 : {
2439 43697 : tmp2 = L_shl( tmp2, sub( 63, q_tmp2 ) );
2440 43697 : q_tmp2 = 63;
2441 43697 : move16();
2442 43697 : IF( EQ_32( tmp2, -1 ) )
2443 : {
2444 0 : tmp2 = 0;
2445 0 : move32();
2446 0 : q_tmp2 = 31;
2447 0 : move16();
2448 : }
2449 : }
2450 13918420 : IF( LT_16( q_CrEne, q_tmp2 ) )
2451 : {
2452 7547430 : realizedOutputEne_fx = L_add( tmp1, L_shr( tmp2, sub( q_tmp2, q_CrEne ) ) );
2453 7547430 : q_realizedOutputEne = q_CrEne;
2454 7547430 : move16();
2455 : }
2456 : ELSE
2457 : {
2458 6370990 : realizedOutputEne_fx = L_add( L_shr( tmp1, sub( q_CrEne, q_tmp2 ) ), tmp2 );
2459 6370990 : q_realizedOutputEne = q_tmp2;
2460 6370990 : move16();
2461 : }
2462 :
2463 13918420 : exp = sub( get_min_scalefactor( hDiracDecBin->ChEneOut_fx[0][bin], hDiracDecBin->ChEneOut_fx[1][bin] ), 1 );
2464 13918420 : targetOutputEne_fx = L_add( L_shl( hDiracDecBin->ChEneOut_fx[0][bin], exp ), L_shl( hDiracDecBin->ChEneOut_fx[1][bin], exp ) );
2465 13918420 : q_targetOutputEne = add( hDiracDecBin->q_ChEneOut, exp );
2466 :
2467 13918420 : exp = sub( norm_l( targetOutputEne_fx ), 2 );
2468 13918420 : targetOutputEne_fx = L_shl( targetOutputEne_fx, exp );
2469 13918420 : q_targetOutputEne = add( q_targetOutputEne, exp );
2470 13918420 : exp = sub( norm_l( -realizedOutputEne_fx ), 2 );
2471 13918420 : realizedOutputEne_fx = L_shl( -realizedOutputEne_fx, exp );
2472 13918420 : q_realizedOutputEne = add( q_realizedOutputEne, exp );
2473 13918420 : IF( LT_16( q_realizedOutputEne, q_targetOutputEne ) )
2474 : {
2475 103453 : missingOutputEne_fx = L_max( 0, L_add( L_shr( targetOutputEne_fx, sub( q_targetOutputEne, q_realizedOutputEne ) ), realizedOutputEne_fx ) );
2476 103453 : q_missingOutputEne = q_realizedOutputEne;
2477 103453 : move16();
2478 : }
2479 : ELSE
2480 : {
2481 13814967 : missingOutputEne_fx = L_max( 0, L_add( targetOutputEne_fx, L_shr( realizedOutputEne_fx, sub( q_realizedOutputEne, q_targetOutputEne ) ) ) );
2482 13814967 : q_missingOutputEne = q_targetOutputEne;
2483 13814967 : move16();
2484 : }
2485 :
2486 13918420 : tmp1 = BASOP_Util_Add_Mant32Exp( tmp2, sub( 31, q_tmp2 ), missingOutputEne_fx, sub( 31, q_missingOutputEne ), &exp1 );
2487 :
2488 : {
2489 13918420 : tmp2 = BASOP_Util_Add_Mant32Exp( tmp2, sub( 31, q_tmp2 ), EPSILON_MANT, EPSILON_EXP, &exp2 );
2490 13918420 : tmp2 = ISqrt32( tmp2, &exp2 );
2491 13918420 : gain_fx = Mpy_32_32( tmp2, Sqrt32( tmp1, &exp1 ) );
2492 13918420 : q_gain = sub( 31, add( exp2, exp1 ) );
2493 : }
2494 :
2495 :
2496 : // 1073741824 = 4 in Q28
2497 13918420 : IF( LT_16( q_gain, Q28 ) )
2498 : {
2499 269570 : gain_fx = L_min( gain_fx, L_shr( 1073741824, sub( Q28, q_gain ) ) );
2500 : }
2501 : ELSE
2502 : {
2503 13648850 : gain_fx = L_min( L_shr( gain_fx, sub( q_gain, Q28 ) ), 1073741824 );
2504 13648850 : q_gain = Q28;
2505 13648850 : move16();
2506 : }
2507 :
2508 41755260 : FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
2509 : {
2510 83510520 : FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
2511 : {
2512 55673680 : Mre_fx[chA][chB] = Mpy_32_32( Mre_fx[chA][chB], gain_fx );
2513 55673680 : move32();
2514 55673680 : Mim_fx[chA][chB] = Mpy_32_32( Mim_fx[chA][chB], gain_fx );
2515 55673680 : move32();
2516 : }
2517 : }
2518 13918420 : q_M = sub( add( q_M, q_gain ), 31 );
2519 :
2520 13918420 : exp = s_min( L_norm_arr( Mre_fx[0], BINAURAL_CHANNELS * BINAURAL_CHANNELS ), L_norm_arr( Mim_fx[0], BINAURAL_CHANNELS * BINAURAL_CHANNELS ) );
2521 13918420 : scale_sig32( Mre_fx[0], BINAURAL_CHANNELS * BINAURAL_CHANNELS, exp );
2522 13918420 : scale_sig32( Mim_fx[0], BINAURAL_CHANNELS * BINAURAL_CHANNELS, exp );
2523 13918420 : q_M = add( q_M, exp );
2524 :
2525 13918420 : exp = s_min( L_norm_arr( MdecRe_fx[0], BINAURAL_CHANNELS * BINAURAL_CHANNELS ), L_norm_arr( MdecIm_fx[0], BINAURAL_CHANNELS * BINAURAL_CHANNELS ) );
2526 13918420 : scale_sig32( MdecRe_fx[0], BINAURAL_CHANNELS * BINAURAL_CHANNELS, exp );
2527 13918420 : scale_sig32( MdecIm_fx[0], BINAURAL_CHANNELS * BINAURAL_CHANNELS, exp );
2528 13918420 : q_Mdec = add( q_Mdec, exp );
2529 :
2530 13918420 : q_processMtx_bin = q_processMtx[bin];
2531 13918420 : q_processMtxDec_bin = q_processMtxDec[bin];
2532 13918420 : move16();
2533 13918420 : move16();
2534 : /* Store processing matrices */
2535 41755260 : FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
2536 : {
2537 83510520 : FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
2538 : {
2539 55673680 : hDiracDecBin->processMtxRePrev_fx[chA][chB][bin] = hDiracDecBin->processMtxRe_fx[chA][chB][bin]; // q_processMtx_bin
2540 55673680 : move16();
2541 55673680 : hDiracDecBin->processMtxImPrev_fx[chA][chB][bin] = hDiracDecBin->processMtxIm_fx[chA][chB][bin]; // q_processMtx_bin
2542 55673680 : move16();
2543 :
2544 55673680 : hDiracDecBin->processMtxDecRePrev_fx[chA][chB][bin] = hDiracDecBin->processMtxDecRe_fx[chA][chB][bin]; // q_processMtxDec_bin
2545 55673680 : move16();
2546 55673680 : hDiracDecBin->processMtxDecImPrev_fx[chA][chB][bin] = hDiracDecBin->processMtxDecIm_fx[chA][chB][bin]; // q_processMtxDec_bin
2547 55673680 : move16();
2548 :
2549 55673680 : hDiracDecBin->processMtxRe_fx[chA][chB][bin] = extract_h( Mre_fx[chA][chB] ); // q_M -16
2550 55673680 : move16();
2551 55673680 : hDiracDecBin->processMtxIm_fx[chA][chB][bin] = extract_h( Mim_fx[chA][chB] ); // q_M -16
2552 55673680 : move16();
2553 :
2554 55673680 : hDiracDecBin->processMtxDecRe_fx[chA][chB][bin] = extract_h( MdecRe_fx[chA][chB] ); // q_Mdec -16
2555 55673680 : move16();
2556 55673680 : hDiracDecBin->processMtxDecIm_fx[chA][chB][bin] = extract_h( MdecIm_fx[chA][chB] ); // q_Mdec -16
2557 55673680 : move16();
2558 : }
2559 : }
2560 13918420 : q_processMtxPrev[bin] = q_processMtx_bin;
2561 13918420 : move16();
2562 13918420 : q_processMtxDecPrev[bin] = q_processMtxDec_bin;
2563 13918420 : move16();
2564 13918420 : q_processMtx[bin] = sub( q_M, 16 );
2565 13918420 : move16();
2566 13918420 : q_processMtxDec[bin] = sub( q_Mdec, 16 );
2567 13918420 : move16();
2568 :
2569 13918420 : IF( separateCenterChannelRendering )
2570 : {
2571 : /* The rendering of the separate center channel in masa + mono mode.
2572 : * The center channel is processed with a gain factor 0.8414f to match the loudness of different processing paths */
2573 : Word32 lRealp_fx, lImagp_fx, rRealp_fx, rImagp_fx;
2574 : Word32 gainFactor_fx;
2575 : Word16 q_tmp_sq;
2576 450660 : Word16 aziDeg = 0;
2577 450660 : move16();
2578 450660 : Word16 eleDeg = 0;
2579 450660 : move16();
2580 450660 : UWord8 instantChange = 0;
2581 450660 : move16();
2582 :
2583 450660 : exp = sub( 31, hDiracDecBin->q_earlyPartEneCorrection );
2584 450660 : tmp1 = Sqrt32( hDiracDecBin->earlyPartEneCorrection_fx[bin], &exp );
2585 450660 : q_tmp_sq = sub( 31, exp );
2586 450660 : IF( EQ_16( ivas_format, MASA_ISM_FORMAT ) )
2587 : {
2588 444660 : Word32 gainfactor_fx = L_shl( (Word32) OMASA_TDREND_MATCHING_GAIN_FX, Q16 ); // constant in Q31 as Word32
2589 444660 : gainFactor_fx = Mpy_32_32( gainfactor_fx, tmp1 ); // 1705746262 = 0.7943f in Q31
2590 : }
2591 : ELSE
2592 : {
2593 6000 : gainFactor_fx = Mpy_32_32( 1806892741, tmp1 ); // 1806892741 = 0.8414f in Q31
2594 : }
2595 450660 : q_gain = sub( add( q_tmp_sq, 31 ), 31 );
2596 :
2597 450660 : q_processMtx_bin = q_processMtx_SCCR[bin];
2598 450660 : move16();
2599 :
2600 1137960 : FOR( chB = 0; chB < nchanSeparateChannels; chB++ )
2601 : {
2602 687300 : IF( EQ_16( ivas_format, MASA_ISM_FORMAT ) )
2603 : {
2604 681300 : IF( EQ_16( ism_mode, ISM_MASA_MODE_DISC ) )
2605 : {
2606 377160 : aziDeg = hMasaIsmData->azimuth_ism[chB][dirac_read_idx];
2607 377160 : move16();
2608 377160 : eleDeg = hMasaIsmData->elevation_ism[chB][dirac_read_idx];
2609 377160 : move16();
2610 : }
2611 : ELSE
2612 : {
2613 304140 : aziDeg = hMasaIsmData->azimuth_separated_ism[dirac_read_idx];
2614 304140 : move16();
2615 304140 : eleDeg = hMasaIsmData->elevation_separated_ism[dirac_read_idx];
2616 304140 : move16();
2617 304140 : instantChange = 1;
2618 304140 : move16();
2619 : }
2620 : }
2621 :
2622 2061900 : FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
2623 : {
2624 1374600 : hDiracDecBin->processMtxRePrev_fx[chA][chB + 2][bin] = hDiracDecBin->processMtxRe_fx[chA][chB + 2][bin];
2625 1374600 : move16();
2626 1374600 : hDiracDecBin->processMtxImPrev_fx[chA][chB + 2][bin] = hDiracDecBin->processMtxIm_fx[chA][chB + 2][bin];
2627 1374600 : move16();
2628 : }
2629 687300 : q_processMtxPrev_SCCR[bin] = q_processMtx_bin;
2630 687300 : move16();
2631 :
2632 : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
2633 687300 : getDirectPartGains_fx( bin, aziDeg, eleDeg, &lRealp_fx, &lImagp_fx, &rRealp_fx, &rImagp_fx, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache[chB], isHeadtracked, *hDiracDecBin->phHrtfParambin );
2634 : #else
2635 : getDirectPartGains_fx( bin, aziDeg, eleDeg, &lRealp_fx, &lImagp_fx, &rRealp_fx, &rImagp_fx, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache[chB], isHeadtracked );
2636 : #endif
2637 :
2638 687300 : hDiracDecBin->processMtxRe_fx[0][chB + 2][bin] = extract_h( Mpy_32_32( lRealp_fx, gainFactor_fx ) );
2639 687300 : move16();
2640 687300 : hDiracDecBin->processMtxIm_fx[0][chB + 2][bin] = extract_h( Mpy_32_32( lImagp_fx, gainFactor_fx ) );
2641 687300 : move16();
2642 687300 : hDiracDecBin->processMtxRe_fx[1][chB + 2][bin] = extract_h( Mpy_32_32( rRealp_fx, gainFactor_fx ) );
2643 687300 : move16();
2644 687300 : hDiracDecBin->processMtxIm_fx[1][chB + 2][bin] = extract_h( Mpy_32_32( rImagp_fx, gainFactor_fx ) );
2645 687300 : move16();
2646 687300 : q_processMtx_SCCR[bin] = sub( sub( add( Q28, q_gain ), 31 ), 16 );
2647 687300 : move16();
2648 :
2649 687300 : IF( instantChange )
2650 : {
2651 912420 : FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
2652 : {
2653 608280 : hDiracDecBin->processMtxRePrev_fx[chA][chB + 2][bin] = hDiracDecBin->processMtxRe_fx[chA][chB + 2][bin];
2654 608280 : move16();
2655 608280 : hDiracDecBin->processMtxImPrev_fx[chA][chB + 2][bin] = hDiracDecBin->processMtxIm_fx[chA][chB + 2][bin];
2656 608280 : move16();
2657 : }
2658 304140 : q_processMtxPrev_SCCR[bin] = q_processMtx_SCCR[bin];
2659 304140 : move16();
2660 : }
2661 : }
2662 : }
2663 : }
2664 : /* Aligning Q-factors of all bins in the processing matrices to a common Q-factor */
2665 282525 : minimum_s( q_processMtx, nBins, &hDiracDecBin->q_processMtx );
2666 282525 : minimum_s( q_processMtxPrev, nBins, &hDiracDecBin->q_processMtxPrev );
2667 282525 : IF( separateCenterChannelRendering )
2668 : {
2669 9753 : minimum_s( q_processMtx_SCCR, nBins, &hDiracDecBin->q_processMtxSCCR );
2670 9753 : minimum_s( q_processMtxPrev_SCCR, nBins, &hDiracDecBin->q_processMtxPrevSCCR );
2671 : }
2672 282525 : hDiracDecBin->q_processMtx = s_min( hDiracDecBin->q_processMtx, hDiracDecBin->q_processMtxSCCR );
2673 282525 : move16();
2674 282525 : hDiracDecBin->q_processMtxPrev = s_min( hDiracDecBin->q_processMtxPrev, hDiracDecBin->q_processMtxPrevSCCR );
2675 282525 : move16();
2676 282525 : hDiracDecBin->q_processMtxSCCR = hDiracDecBin->q_processMtx;
2677 282525 : move16();
2678 282525 : hDiracDecBin->q_processMtxPrevSCCR = hDiracDecBin->q_processMtxPrev;
2679 282525 : move16();
2680 282525 : minimum_s( q_processMtxDec, nBins, &hDiracDecBin->q_processMtxDec );
2681 282525 : minimum_s( q_processMtxDecPrev, nBins, &hDiracDecBin->q_processMtxDecPrev );
2682 :
2683 14200945 : FOR( bin = 0; bin < nBins; bin++ )
2684 : {
2685 41755260 : FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
2686 : {
2687 83510520 : FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
2688 : {
2689 55673680 : hDiracDecBin->processMtxRe_fx[chA][chB][bin] = shr( hDiracDecBin->processMtxRe_fx[chA][chB][bin], sub( q_processMtx[bin], hDiracDecBin->q_processMtx ) ); // hDiracDecBin->q_processMtx
2690 55673680 : move16();
2691 55673680 : hDiracDecBin->processMtxIm_fx[chA][chB][bin] = shr( hDiracDecBin->processMtxIm_fx[chA][chB][bin], sub( q_processMtx[bin], hDiracDecBin->q_processMtx ) ); // hDiracDecBin->q_processMtx
2692 55673680 : move16();
2693 55673680 : hDiracDecBin->processMtxRePrev_fx[chA][chB][bin] = shr( hDiracDecBin->processMtxRePrev_fx[chA][chB][bin], sub( q_processMtxPrev[bin], hDiracDecBin->q_processMtxPrev ) ); // hDiracDecBin->q_processMtxPrev
2694 55673680 : move16();
2695 55673680 : hDiracDecBin->processMtxImPrev_fx[chA][chB][bin] = shr( hDiracDecBin->processMtxImPrev_fx[chA][chB][bin], sub( q_processMtxPrev[bin], hDiracDecBin->q_processMtxPrev ) ); // hDiracDecBin->q_processMtxPrev
2696 55673680 : move16();
2697 55673680 : hDiracDecBin->processMtxDecRe_fx[chA][chB][bin] = shr( hDiracDecBin->processMtxDecRe_fx[chA][chB][bin], sub( q_processMtxDec[bin], hDiracDecBin->q_processMtxDec ) ); // hDiracDecBin->q_processMtxDec
2698 55673680 : move16();
2699 55673680 : hDiracDecBin->processMtxDecIm_fx[chA][chB][bin] = shr( hDiracDecBin->processMtxDecIm_fx[chA][chB][bin], sub( q_processMtxDec[bin], hDiracDecBin->q_processMtxDec ) ); // hDiracDecBin->q_processMtxDec
2700 55673680 : move16();
2701 55673680 : hDiracDecBin->processMtxDecRePrev_fx[chA][chB][bin] = shr( hDiracDecBin->processMtxDecRePrev_fx[chA][chB][bin], sub( q_processMtxDecPrev[bin], hDiracDecBin->q_processMtxDecPrev ) ); // hDiracDecBin->q_processMtxDecPrev
2702 55673680 : move16();
2703 55673680 : hDiracDecBin->processMtxDecImPrev_fx[chA][chB][bin] = shr( hDiracDecBin->processMtxDecImPrev_fx[chA][chB][bin], sub( q_processMtxDecPrev[bin], hDiracDecBin->q_processMtxDecPrev ) ); // hDiracDecBin->q_processMtxDecPrev
2704 55673680 : move16();
2705 : }
2706 27836840 : IF( separateCenterChannelRendering )
2707 : {
2708 2275920 : FOR( chB = 0; chB < nchanSeparateChannels; chB++ )
2709 : {
2710 1374600 : hDiracDecBin->processMtxRe_fx[chA][chB + 2][bin] = shr( hDiracDecBin->processMtxRe_fx[chA][chB + 2][bin], sub( q_processMtx_SCCR[bin], hDiracDecBin->q_processMtx ) ); // hDiracDecBin->q_processMtx
2711 1374600 : move16();
2712 1374600 : hDiracDecBin->processMtxIm_fx[chA][chB + 2][bin] = shr( hDiracDecBin->processMtxIm_fx[chA][chB + 2][bin], sub( q_processMtx_SCCR[bin], hDiracDecBin->q_processMtx ) ); // hDiracDecBin->q_processMtx
2713 1374600 : move16();
2714 1374600 : hDiracDecBin->processMtxRePrev_fx[chA][chB + 2][bin] = shr( hDiracDecBin->processMtxRePrev_fx[chA][chB + 2][bin], sub( q_processMtxPrev_SCCR[bin], hDiracDecBin->q_processMtxPrev ) ); // hDiracDecBin->q_processMtxPrev
2715 1374600 : move16();
2716 1374600 : hDiracDecBin->processMtxImPrev_fx[chA][chB + 2][bin] = shr( hDiracDecBin->processMtxImPrev_fx[chA][chB + 2][bin], sub( q_processMtxPrev_SCCR[bin], hDiracDecBin->q_processMtxPrev ) ); // hDiracDecBin->q_processMtxPrev
2717 1374600 : move16();
2718 : }
2719 : }
2720 : }
2721 : }
2722 :
2723 282525 : return;
2724 : }
2725 :
2726 282525 : static void ivas_dirac_dec_binaural_process_output_fx(
2727 : DIRAC_DEC_BIN_HANDLE hDiracDecBin,
2728 : SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom,
2729 : HANDLE_CLDFB_FILTER_BANK cldfbSynDec[MAX_OUTPUT_CHANNELS],
2730 : Word32 *output_fx[], /*q_out*/
2731 : Word16 *q_out,
2732 : Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*q_input*/
2733 : Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*q_input*/
2734 : const Word16 q_input,
2735 : const Word16 max_band_decorr,
2736 : const Word16 numInChannels,
2737 : const Word16 processReverb,
2738 : const Word16 subframe,
2739 : const Word16 q_mat,
2740 : Word32 outRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
2741 : Word32 outIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
2742 : Word32 reverbRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
2743 : Word32 reverbIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
2744 : Word32 decorrRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
2745 : Word32 decorrIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
2746 : Word16 *Q_inp_mix,
2747 : const Word8 recompute )
2748 : {
2749 : Word16 slot, bin, chA, chB;
2750 : Word16 nBins;
2751 : Word16 offsetSamples;
2752 : Word16 nSlots;
2753 :
2754 282525 : nBins = hSpatParamRendCom->num_freq_bands;
2755 282525 : offsetSamples = 0;
2756 282525 : nSlots = hSpatParamRendCom->subframe_nbslots[subframe];
2757 282525 : move16();
2758 282525 : move16();
2759 282525 : move16();
2760 :
2761 : Word32 decSlotRe_fx[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX], decSlotIm_fx[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX];
2762 : Word32 outSlotRe_fx[CLDFB_NO_CHANNELS_MAX], outSlotIm_fx[CLDFB_NO_CHANNELS_MAX];
2763 : Word16 q_inp[6][CLDFB_SLOTS_PER_SUBFRAME];
2764 : Word16 interpVal_fx;
2765 : Word32 *decSlotRePointer_fx;
2766 : Word32 *decSlotImPointer_fx;
2767 282525 : Word16 q_inp_mix, q_reverb = 31;
2768 282525 : move16();
2769 282525 : Word16 ch_len = s_max( 4, numInChannels );
2770 : Word16 eff_q;
2771 :
2772 :
2773 282525 : IF( processReverb )
2774 : {
2775 118411 : if ( recompute == 1 )
2776 : {
2777 : /* Process second / room effect part of binaural output when needed */
2778 118411 : ivas_binaural_reverb_processSubframe_fx( hDiracDecBin->hReverb, numInChannels, nSlots, inRe_fx, inIm_fx, reverbRe_fx, reverbIm_fx );
2779 : }
2780 : }
2781 :
2782 282525 : IF( EQ_16( recompute, 1 ) )
2783 : {
2784 : // scaling input and reverb to same q//
2785 : // input scaling is to maintain precision in ivas_dirac_dec_decorrelate_slot fn//
2786 282525 : Word16 shift = s_min( L_norm_arr( cldfbSynDec[0]->cldfb_state_fx, cldfbSynDec[0]->p_filter_length ), L_norm_arr( cldfbSynDec[1]->cldfb_state_fx, cldfbSynDec[1]->p_filter_length ) );
2787 282525 : q_inp_mix = 31;
2788 282525 : move16();
2789 :
2790 1414793 : FOR( Word16 i = 0; i < ch_len; i++ )
2791 :
2792 : {
2793 5646832 : FOR( Word16 j = 0; j < nSlots; j++ )
2794 : {
2795 4514564 : q_inp[i][j] = s_min( L_norm_arr( inRe_fx[i][j], nBins ), L_norm_arr( inIm_fx[i][j], nBins ) );
2796 4514564 : move16();
2797 4514564 : test();
2798 4514564 : IF( ( processReverb && EQ_16( recompute, 1 ) ) && LT_16( i, 2 ) )
2799 : {
2800 942500 : q_reverb = s_min( L_norm_arr( reverbRe_fx[i][j], CLDFB_NO_CHANNELS_MAX ), L_norm_arr( reverbIm_fx[i][j], CLDFB_NO_CHANNELS_MAX ) );
2801 942500 : q_inp[i][j] = s_min( q_reverb, q_inp[i][j] );
2802 942500 : move16();
2803 : }
2804 4514564 : q_inp_mix = s_min( q_inp[i][j], q_inp_mix );
2805 : }
2806 : }
2807 :
2808 282525 : q_inp_mix = sub( q_inp_mix, 3 ); // gaurded bits//
2809 :
2810 282525 : Word16 cldfb_state_shift = sub( add( add( q_inp_mix, q_mat ), sub( q_input, 16 ) ), cldfbSynDec[0]->Q_cldfb_state );
2811 282525 : IF( GT_16( cldfb_state_shift, shift ) )
2812 : {
2813 0 : q_inp_mix = sub( add( q_inp_mix, shift ), cldfb_state_shift );
2814 0 : cldfb_state_shift = shift;
2815 0 : move16();
2816 : }
2817 :
2818 :
2819 282525 : eff_q = sub( add( q_inp_mix, q_mat ), 15 );
2820 :
2821 1414793 : FOR( Word16 i = 0; i < ch_len; i++ )
2822 :
2823 : {
2824 5646832 : FOR( Word16 j = 0; j < nSlots; j++ )
2825 : {
2826 :
2827 4514564 : scale_sig32( inRe_fx[i][j], nBins, q_inp_mix ); /*q_input + q_inp_mix*/
2828 4514564 : scale_sig32( inIm_fx[i][j], nBins, q_inp_mix ); /*q_input + q_inp_mix*/
2829 4514564 : test();
2830 4514564 : IF( ( processReverb && EQ_16( recompute, 1 ) ) && LT_16( i, 2 ) )
2831 : {
2832 942500 : scale_sig32( reverbRe_fx[i][j], CLDFB_NO_CHANNELS_MAX, eff_q ); /*q_inp_mix+q_mat-15*/
2833 942500 : scale_sig32( reverbIm_fx[i][j], CLDFB_NO_CHANNELS_MAX, eff_q ); /*q_inp_mix+q_mat-15*/
2834 : }
2835 : }
2836 : }
2837 :
2838 : // scaling cldfb states to q_result-1//
2839 282525 : scale_sig32( cldfbSynDec[0]->cldfb_state_fx, cldfbSynDec[0]->p_filter_length, cldfb_state_shift );
2840 282525 : cldfbSynDec[0]->Q_cldfb_state = add( cldfbSynDec[0]->Q_cldfb_state, cldfb_state_shift );
2841 282525 : scale_sig32( cldfbSynDec[1]->cldfb_state_fx, cldfbSynDec[1]->p_filter_length, cldfb_state_shift );
2842 282525 : cldfbSynDec[1]->Q_cldfb_state = add( cldfbSynDec[1]->Q_cldfb_state, cldfb_state_shift );
2843 282525 : move16();
2844 282525 : move16();
2845 282525 : *Q_inp_mix = q_inp_mix;
2846 282525 : move16();
2847 : }
2848 : ELSE
2849 : {
2850 0 : q_inp_mix = *Q_inp_mix;
2851 : }
2852 :
2853 282525 : q_inp_mix = add( q_inp_mix, q_input );
2854 :
2855 282525 : interpVal_fx = 0;
2856 282525 : move16();
2857 282525 : Word16 q_result = sub( add( q_inp_mix, q_mat ), 15 ); // setting it prior//
2858 282525 : cldfbSynDec[0]->Q_cldfb_state = sub( q_result, 1 );
2859 282525 : cldfbSynDec[1]->Q_cldfb_state = sub( q_result, 1 );
2860 282525 : move16();
2861 282525 : move16();
2862 :
2863 1409046 : FOR( slot = 0; slot < nSlots; slot++ )
2864 : {
2865 1126521 : IF( NE_16( slot, sub( nSlots, 1 ) ) )
2866 : {
2867 843996 : interpVal_fx = add( interpVal_fx, slot_fx[nSlots - 1] ); /*Q15*/
2868 : }
2869 : ELSE
2870 : {
2871 282525 : interpVal_fx = 32767; /*Q15*/
2872 282525 : move16();
2873 : }
2874 1126521 : test();
2875 1126521 : IF( !hDiracDecBin->useTdDecorr && ( max_band_decorr > 0 ) )
2876 : {
2877 564275 : if ( recompute == 1 )
2878 : {
2879 564275 : ivas_dirac_dec_decorrelate_slot_fx( hDiracDecBin, nBins, slot, inRe_fx, inIm_fx, q_inp_mix, decSlotRe_fx, decSlotIm_fx );
2880 1692825 : FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
2881 : {
2882 1128550 : Copy32( decSlotRe_fx[chA], decorrRe_fx[chA][slot], CLDFB_NO_CHANNELS_MAX );
2883 1128550 : Copy32( decSlotIm_fx[chA], decorrIm_fx[chA][slot], CLDFB_NO_CHANNELS_MAX );
2884 : }
2885 : }
2886 : else
2887 : {
2888 0 : FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
2889 : {
2890 0 : Copy32( decorrRe_fx[chA][slot], decSlotRe_fx[chA], CLDFB_NO_CHANNELS_MAX );
2891 0 : Copy32( decorrIm_fx[chA][slot], decSlotIm_fx[chA], CLDFB_NO_CHANNELS_MAX );
2892 : }
2893 : }
2894 : }
2895 :
2896 3379563 : FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
2897 : {
2898 : Word32 *outSlotRePr_fx, *outSlotImPr_fx; /* Pointers needed for function call compatibility */
2899 :
2900 2253042 : set_zero_fx( outSlotRe_fx, CLDFB_NO_CHANNELS_MAX );
2901 2253042 : set_zero_fx( outSlotIm_fx, CLDFB_NO_CHANNELS_MAX );
2902 :
2903 : /* Processing of the first / HRTF part of the binaural output. */
2904 6873178 : FOR( chB = 0; chB < numInChannels; chB++ )
2905 : {
2906 4620136 : IF( LT_16( chB, BINAURAL_CHANNELS ) )
2907 : {
2908 : /* Decorrelator signal for TD decorrelation is stored in two input channels above the two normal inputs.
2909 : * It should be noted that TD decorrelation is used only in cases where numInChannels is 2. If this
2910 : * changes, additional adjustments are required. When using CLDFB decorrelator, we simply assign the
2911 : * pointers to buffers. */
2912 4506084 : IF( hDiracDecBin->useTdDecorr )
2913 : {
2914 1739892 : decSlotRePointer_fx = inRe_fx[chB + 2][slot];
2915 1739892 : decSlotImPointer_fx = inIm_fx[chB + 2][slot];
2916 : }
2917 : ELSE
2918 : {
2919 2766192 : decSlotRePointer_fx = decSlotRe_fx[chB];
2920 2766192 : decSlotImPointer_fx = decSlotIm_fx[chB];
2921 : }
2922 : }
2923 : ELSE
2924 : {
2925 114052 : decSlotRePointer_fx = NULL; /* below these pointers are used only for chB < 2 */
2926 114052 : decSlotImPointer_fx = NULL;
2927 : }
2928 :
2929 :
2930 232019736 : FOR( bin = 0; bin < nBins; bin++ )
2931 : {
2932 : Word16 gain;
2933 : /* Mixing using the formulated processing matrix M */
2934 227399600 : gain = add( mult( sub( 32767, interpVal_fx ), hDiracDecBin->processMtxRePrev_fx[chA][chB][bin] ), mult( interpVal_fx, hDiracDecBin->processMtxRe_fx[chA][chB][bin] ) ); // Q11
2935 :
2936 227399600 : outSlotRe_fx[bin] = Madd_32_16( outSlotRe_fx[bin], inRe_fx[chB][slot][bin], gain ); // q_inp_mix-4//q_result
2937 227399600 : outSlotIm_fx[bin] = Madd_32_16( outSlotIm_fx[bin], inIm_fx[chB][slot][bin], gain ); // q_inp_mix-4//q_result
2938 227399600 : move32();
2939 227399600 : move32();
2940 :
2941 227399600 : gain = add( mult( sub( 32767, interpVal_fx ), hDiracDecBin->processMtxImPrev_fx[chA][chB][bin] ), mult( interpVal_fx, hDiracDecBin->processMtxIm_fx[chA][chB][bin] ) ); // Q11
2942 :
2943 : // interpVal * hDiracDecBin->processMtxIm[chA][chB][bin];
2944 227399600 : outSlotRe_fx[bin] = Msub_32_16( outSlotRe_fx[bin], inIm_fx[chB][slot][bin], gain ); // q_inp_mix-4//q_result
2945 227399600 : outSlotIm_fx[bin] = Madd_32_16( outSlotIm_fx[bin], inRe_fx[chB][slot][bin], gain ); // q_inp_mix-4//q_result
2946 :
2947 227399600 : move32();
2948 227399600 : move32();
2949 :
2950 : /* Mixing decorrelated signals using the formulated residual processing matrix Mdec */
2951 227399600 : test();
2952 227399600 : IF( LT_16( bin, max_band_decorr ) && LT_16( chB, 2 ) )
2953 : {
2954 119554900 : gain = add( mult( sub( 32767, interpVal_fx ), hDiracDecBin->processMtxDecRePrev_fx[chA][chB][bin] ), mult( interpVal_fx, hDiracDecBin->processMtxDecRe_fx[chA][chB][bin] ) ); // Q11
2955 : // interpVal * hDiracDecBin->processMtxDecRe[chA][chB][bin];
2956 119554900 : outSlotRe_fx[bin] = Madd_32_16( outSlotRe_fx[bin], decSlotRePointer_fx[bin], gain ); // q_inp_mix-4//q_result
2957 119554900 : outSlotIm_fx[bin] = Madd_32_16( outSlotIm_fx[bin], decSlotImPointer_fx[bin], gain ); // q_inp_mix-4//q_result
2958 119554900 : move32();
2959 119554900 : move32();
2960 :
2961 :
2962 119554900 : gain = add( mult( sub( 32767, interpVal_fx ), hDiracDecBin->processMtxDecImPrev_fx[chA][chB][bin] ), mult( interpVal_fx, hDiracDecBin->processMtxDecIm_fx[chA][chB][bin] ) ); // Q11
2963 119554900 : outSlotRe_fx[bin] = Msub_32_16( outSlotRe_fx[bin], decSlotImPointer_fx[bin], gain ); // q_inp_mix-4//q_result
2964 119554900 : outSlotIm_fx[bin] = Madd_32_16( outSlotIm_fx[bin], decSlotRePointer_fx[bin], gain ); // q_inp_mix-4//q_result
2965 119554900 : move32();
2966 119554900 : move32();
2967 : }
2968 : }
2969 : }
2970 :
2971 :
2972 2253042 : IF( processReverb )
2973 : {
2974 : /* Combine second (reverb) part with the first (HRTF) part to obtain binaural output signal with room effect */
2975 942500 : v_add_fx( outSlotRe_fx, reverbRe_fx[chA][slot], outSlotRe_fx, CLDFB_NO_CHANNELS_MAX );
2976 942500 : v_add_fx( outSlotIm_fx, reverbIm_fx[chA][slot], outSlotIm_fx, CLDFB_NO_CHANNELS_MAX );
2977 : }
2978 :
2979 :
2980 2253042 : outSlotRePr_fx = &( outSlotRe_fx[0] );
2981 2253042 : outSlotImPr_fx = &( outSlotIm_fx[0] );
2982 :
2983 2253042 : IF( outRe_fx != NULL && outIm_fx != NULL )
2984 : {
2985 : /* provide the data outside in CLDFB domain => mainly for split rendering */
2986 0 : Copy32( outSlotRePr_fx, outRe_fx[chA][slot], CLDFB_NO_CHANNELS_MAX );
2987 0 : Copy32( outSlotImPr_fx, outIm_fx[chA][slot], CLDFB_NO_CHANNELS_MAX );
2988 0 : Scale_sig32( outRe_fx[chA][slot], CLDFB_NO_CHANNELS_MAX, sub( Q6, q_result ) ); // Q6
2989 0 : Scale_sig32( outIm_fx[chA][slot], CLDFB_NO_CHANNELS_MAX, sub( Q6, q_result ) ); // Q6
2990 : }
2991 2253042 : if ( recompute == 1 )
2992 : {
2993 : /* Inverse filter bank */
2994 2253042 : cldfbSynthesis_ivas_fx( &outSlotRePr_fx, &outSlotImPr_fx, &( output_fx[chA][nBins * slot + offsetSamples] ), nBins, 0, 0, cldfbSynDec[chA] );
2995 2253042 : cldfbSynDec[chA]->Q_cldfb_state = sub( q_result, 1 );
2996 2253042 : move16();
2997 : }
2998 : }
2999 : }
3000 282525 : if ( recompute == 1 )
3001 : {
3002 282525 : *q_out = sub( q_result, 1 );
3003 282525 : move16();
3004 : }
3005 :
3006 282525 : return;
3007 : }
3008 :
3009 :
3010 72000 : static void adaptTransportSignalsHeadtracked_fx(
3011 : COMBINED_ORIENTATION_HANDLE hHeadTrackData,
3012 : Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*q_inp*/
3013 : Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*q_inp*/
3014 : Word16 q_inp,
3015 : const Word16 nBins,
3016 : const Word16 nSlots,
3017 : Word32 Rmat[3][3] /*Q30*/ )
3018 : {
3019 : Word16 slot, ch, bin, louderCh;
3020 : Word32 mono_factor_ILD, mono_factor;
3021 : Word32 y_val, mono_factor_rotation, ene_proc, ene_target, ILD;
3022 : Word16 ene_proc_e, ene_target_e;
3023 : Word16 max_band;
3024 : Word32 eqVal;
3025 72000 : Word16 band_idx, bin_lo, bin_hi, norm, shift = 31;
3026 : Word32 temp_div;
3027 : Word16 e_div, is_zero, i;
3028 72000 : move16();
3029 :
3030 216000 : FOR( i = 0; i < 2; i++ )
3031 : {
3032 720000 : FOR( Word16 j = 0; j < nSlots; j++ )
3033 : {
3034 576000 : norm = s_min( L_norm_arr( inRe_fx[i][j], nBins ), L_norm_arr( inIm_fx[i][j], nBins ) );
3035 576000 : shift = s_min( norm, shift );
3036 : }
3037 : }
3038 :
3039 : /* Determine head-orientation-based mono factor.
3040 : Rmat[1][1] entry informs how close the ears are aligned according to transport signals. */
3041 :
3042 72000 : y_val = L_sub( ONE_IN_Q30, L_abs( Rmat[1][1] ) ); // Q30
3043 72000 : mono_factor_rotation = Mpy_32_16_1( L_sub( y_val, ADAPT_HTPROTO_ROT_LIM_0_FX ), TWO_POINT_FIVE_IN_Q13 ); // Q28
3044 72000 : mono_factor_rotation = L_max( 0, L_min( ONE_IN_Q28, mono_factor_rotation ) );
3045 :
3046 72000 : IF( EQ_32( mono_factor_rotation, ONE_IN_Q28 ) )
3047 : {
3048 19453 : mono_factor_rotation = ONE_IN_Q31;
3049 : }
3050 : ELSE
3051 : {
3052 52547 : mono_factor_rotation = L_shl( mono_factor_rotation, 3 ); // Q31
3053 : }
3054 72000 : move32();
3055 :
3056 : /* Adapt transport signals in frequency bands */
3057 : /* 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 */
3058 :
3059 72000 : max_band = 0;
3060 72000 : move16();
3061 1746000 : WHILE( max_band < MASA_FREQUENCY_BANDS && MASA_band_grouping_24[max_band] < nBins )
3062 : {
3063 1674000 : max_band = add( max_band, 1 );
3064 : }
3065 :
3066 72000 : shift = sub( shift, 5 );
3067 : // 5 is gaurded bits needed//
3068 : Word32 re, img, temp;
3069 : Word16 s, q_band_nrg, q_temp[2];
3070 1746000 : FOR( band_idx = 0; band_idx < max_band; band_idx++ )
3071 : {
3072 : Word32 ch_nrg[2]; /* storage for input signal channel energies */
3073 : Word64 W_ch_nrg[2]; /* storage for input signal channel energies */
3074 1674000 : bin_lo = MASA_band_grouping_24[band_idx];
3075 1674000 : bin_hi = s_min( MASA_band_grouping_24[band_idx + 1], (Word16) nBins );
3076 :
3077 5022000 : FOR( ch = 0; ch < 2; ch++ )
3078 : {
3079 3348000 : W_ch_nrg[ch] = 0;
3080 3348000 : move32();
3081 16740000 : FOR( slot = 0; slot < nSlots; slot++ )
3082 : {
3083 39312000 : FOR( bin = bin_lo; bin < bin_hi; bin++ )
3084 : {
3085 25920000 : re = L_shl( inRe_fx[ch][slot][bin], shift );
3086 25920000 : img = L_shl( inIm_fx[ch][slot][bin], shift );
3087 :
3088 25920000 : W_ch_nrg[ch] = W_add( W_ch_nrg[ch], ( W_add( W_mult0_32_32( re, re ), W_mult0_32_32( img, img ) ) ) ); // 2(q_inp +shift)
3089 25920000 : move64();
3090 : }
3091 : }
3092 3348000 : s = W_norm( W_ch_nrg[ch] );
3093 3348000 : ch_nrg[ch] = W_extract_h( W_shl( W_ch_nrg[ch], s ) ); // Q: 2*(q_inp+shift) + s - 32
3094 3348000 : q_temp[ch] = sub( add( shl( add( q_inp, shift ), 1 ), s ), 32 );
3095 3348000 : move32();
3096 3348000 : move16();
3097 :
3098 3348000 : hHeadTrackData->chEneIIR_fx[ch][band_idx] = Mpy_32_16_1( hHeadTrackData->chEneIIR_fx[ch][band_idx], ADAPT_HTPROTO_IIR_FAC_FX ); // q_chEneIIR
3099 3348000 : move32();
3100 3348000 : temp = Mpy_32_16_1( ch_nrg[ch], sub( 32767, ADAPT_HTPROTO_IIR_FAC_FX ) ); // q_temp[ch]
3101 3348000 : IF( LT_16( hHeadTrackData->q_chEneIIR[ch][band_idx], q_temp[ch] ) )
3102 : {
3103 3293874 : hHeadTrackData->chEneIIR_fx[ch][band_idx] = L_add( L_shr( temp, sub( q_temp[ch], hHeadTrackData->q_chEneIIR[ch][band_idx] ) ), hHeadTrackData->chEneIIR_fx[ch][band_idx] ); // hHeadTrackData->q_chEneIIR[ch][band_idx]
3104 : }
3105 : ELSE
3106 : {
3107 54126 : hHeadTrackData->chEneIIR_fx[ch][band_idx] = L_add( L_shr( hHeadTrackData->chEneIIR_fx[ch][band_idx], sub( hHeadTrackData->q_chEneIIR[ch][band_idx], q_temp[ch] ) ), temp ); // q_temp[ch]
3108 : }
3109 3348000 : move32();
3110 3348000 : hHeadTrackData->q_chEneIIR[ch][band_idx] = s_min( hHeadTrackData->q_chEneIIR[ch][band_idx], q_temp[ch] );
3111 3348000 : move16();
3112 : }
3113 : /* Determine ILD */
3114 :
3115 1674000 : IF( EQ_32( L_max( 1, hHeadTrackData->chEneIIR_fx[0][band_idx] ), L_max( 1, hHeadTrackData->chEneIIR_fx[1][band_idx] ) ) )
3116 : {
3117 2272 : ILD = 0;
3118 2272 : move32();
3119 : }
3120 : ELSE
3121 : {
3122 1671728 : temp_div = L_deposit_h( BASOP_Util_Divide3232_Scale( L_max( 1, hHeadTrackData->chEneIIR_fx[0][band_idx] ), L_max( 1, hHeadTrackData->chEneIIR_fx[1][band_idx] ), &e_div ) );
3123 1671728 : e_div = add( e_div, sub( hHeadTrackData->q_chEneIIR[1][band_idx], hHeadTrackData->q_chEneIIR[0][band_idx] ) );
3124 1671728 : temp = BASOP_Util_Log2( temp_div ); // Q25
3125 1671728 : IF( e_div > 0 )
3126 : {
3127 795388 : temp = L_add( temp, L_shl( e_div, 25 ) ); // Q25
3128 : }
3129 : ELSE
3130 : {
3131 876340 : temp = L_sub( temp, L_shl( L_abs( e_div ), 25 ) ); // Q25
3132 : }
3133 :
3134 1671728 : temp = Mpy_32_32( temp, 646462464 ); // logx base 10 = 0.30103* logx base 2//
3135 1671728 : ILD = L_abs( Mpy_32_16_1( temp, 20480 ) ); // Q21
3136 : }
3137 1674000 : IF( BASOP_Util_Cmp_Mant32Exp( hHeadTrackData->chEneIIR_fx[1][band_idx], sub( 31, hHeadTrackData->q_chEneIIR[1][band_idx] ), hHeadTrackData->chEneIIR_fx[0][band_idx], sub( 31, hHeadTrackData->q_chEneIIR[0][band_idx] ) ) > 0 )
3138 : {
3139 1155432 : louderCh = 1;
3140 : }
3141 : ELSE
3142 : {
3143 518568 : louderCh = 0;
3144 : }
3145 1674000 : move16();
3146 :
3147 : /* Determine ILD-based mono factor */
3148 1674000 : mono_factor_ILD = Mpy_32_16_1( L_sub( ILD, ONE_IN_Q21 ), 10911 ); // Q21
3149 :
3150 1674000 : mono_factor_ILD = L_max( 0, L_min( ONE_IN_Q21, mono_factor_ILD ) ); // Q21
3151 :
3152 1674000 : IF( EQ_32( mono_factor_ILD, ONE_IN_Q21 ) )
3153 : {
3154 697078 : mono_factor_ILD = ONE_IN_Q31;
3155 697078 : move32();
3156 : }
3157 : ELSE
3158 : {
3159 976922 : mono_factor_ILD = L_shl( mono_factor_ILD, 10 ); // Q31
3160 : }
3161 :
3162 : /* Combine mono factors */
3163 1674000 : mono_factor = Mpy_32_32( mono_factor_ILD, mono_factor_rotation ); // Q31
3164 :
3165 : /* Mix original audio and sum signal according to determined mono factor */
3166 5022000 : FOR( ch = 0; ch < 2; ch++ )
3167 : {
3168 3348000 : IF( NE_16( ch, louderCh ) )
3169 : {
3170 : Word32 band_nrg;
3171 1674000 : Word64 W_band_nrg = 0;
3172 1674000 : move64();
3173 :
3174 8370000 : FOR( slot = 0; slot < nSlots; slot++ )
3175 : {
3176 19656000 : FOR( bin = bin_lo; bin < bin_hi; bin++ )
3177 : {
3178 : /* mono sum signal with the computed weight + rest from the original channel */
3179 12960000 : inRe_fx[ch][slot][bin] = L_add( ( Mpy_32_32( mono_factor, L_add( inRe_fx[0][slot][bin], inRe_fx[1][slot][bin] ) ) ), ( Mpy_32_32( L_sub( ONE_IN_Q31, mono_factor ), inRe_fx[ch][slot][bin] ) ) );
3180 12960000 : inIm_fx[ch][slot][bin] = L_add( ( Mpy_32_32( mono_factor, L_add( inIm_fx[0][slot][bin], inIm_fx[1][slot][bin] ) ) ), ( Mpy_32_32( L_sub( ONE_IN_Q31, mono_factor ), inIm_fx[ch][slot][bin] ) ) );
3181 12960000 : move32();
3182 12960000 : move32();
3183 12960000 : re = L_shl( inRe_fx[ch][slot][bin], shift ); // q_inp +shift
3184 12960000 : img = L_shl( inIm_fx[ch][slot][bin], shift ); // q_inp +shift
3185 :
3186 12960000 : W_band_nrg = W_add( W_band_nrg, ( W_add( W_mult0_32_32( re, re ), W_mult0_32_32( img, img ) ) ) ); // 2(q_inp + shift)
3187 : }
3188 : }
3189 1674000 : s = W_norm( W_band_nrg );
3190 1674000 : band_nrg = W_extract_h( W_shl( W_band_nrg, s ) ); // Q: 2*(q_inp+shift) + s - 32
3191 1674000 : q_band_nrg = sub( add( shl( add( q_inp, shift ), 1 ), s ), 32 );
3192 :
3193 1674000 : hHeadTrackData->procChEneIIR_fx[ch][band_idx] = Mpy_32_16_1( hHeadTrackData->procChEneIIR_fx[ch][band_idx], ADAPT_HTPROTO_IIR_FAC_FX ); // hHeadTrackData->q_procChEneIIR[ch][band_idx]
3194 1674000 : move32();
3195 :
3196 1674000 : temp = Mpy_32_16_1( band_nrg, sub( 32767, ADAPT_HTPROTO_IIR_FAC_FX ) ); // q_band_nrg
3197 1674000 : IF( LT_16( hHeadTrackData->q_procChEneIIR[ch][band_idx], q_band_nrg ) )
3198 : {
3199 1648613 : hHeadTrackData->procChEneIIR_fx[ch][band_idx] = L_add( L_shr( temp, sub( q_band_nrg, hHeadTrackData->q_procChEneIIR[ch][band_idx] ) ), hHeadTrackData->procChEneIIR_fx[ch][band_idx] ); // hHeadTrackData->q_procChEneIIR[ch][band_idx]
3200 : }
3201 : ELSE
3202 : {
3203 25387 : hHeadTrackData->procChEneIIR_fx[ch][band_idx] = L_add( L_shr( hHeadTrackData->procChEneIIR_fx[ch][band_idx], sub( hHeadTrackData->q_procChEneIIR[ch][band_idx], q_band_nrg ) ), temp ); // q_band_nrg
3204 : }
3205 1674000 : move32();
3206 1674000 : hHeadTrackData->q_procChEneIIR[ch][band_idx] = s_min( hHeadTrackData->q_procChEneIIR[ch][band_idx], q_band_nrg );
3207 1674000 : move16();
3208 : }
3209 : ELSE
3210 : {
3211 : /* processed signal is input. use the original channel, so no need to compute new signals or signal energy */
3212 1674000 : hHeadTrackData->procChEneIIR_fx[ch][band_idx] = Mpy_32_16_1( hHeadTrackData->procChEneIIR_fx[ch][band_idx], ADAPT_HTPROTO_IIR_FAC_FX ); // q_procChEneIIR
3213 1674000 : move32();
3214 :
3215 1674000 : temp = Mpy_32_16_1( ch_nrg[ch], sub( 32767, ADAPT_HTPROTO_IIR_FAC_FX ) );
3216 1674000 : IF( LT_16( hHeadTrackData->q_procChEneIIR[ch][band_idx], q_temp[ch] ) )
3217 : {
3218 1643735 : hHeadTrackData->procChEneIIR_fx[ch][band_idx] = L_add( L_shr( temp, sub( q_temp[ch], hHeadTrackData->q_procChEneIIR[ch][band_idx] ) ), hHeadTrackData->procChEneIIR_fx[ch][band_idx] ); // hHeadTrackData->q_procChEneIIR[ch][band_idx]
3219 : }
3220 : ELSE
3221 : {
3222 30265 : hHeadTrackData->procChEneIIR_fx[ch][band_idx] = L_add( L_shr( hHeadTrackData->procChEneIIR_fx[ch][band_idx], sub( hHeadTrackData->q_procChEneIIR[ch][band_idx], q_temp[ch] ) ), temp ); // q_temp[ch]
3223 : }
3224 1674000 : move32();
3225 1674000 : hHeadTrackData->q_procChEneIIR[ch][band_idx] = s_min( hHeadTrackData->q_procChEneIIR[ch][band_idx], q_temp[ch] );
3226 1674000 : move16();
3227 : }
3228 : }
3229 :
3230 : /* Equalize */
3231 1674000 : ene_target = BASOP_Util_Add_Mant32Exp( hHeadTrackData->chEneIIR_fx[0][band_idx], sub( 31, hHeadTrackData->q_chEneIIR[0][band_idx] ), hHeadTrackData->chEneIIR_fx[1][band_idx], sub( 31, hHeadTrackData->q_chEneIIR[1][band_idx] ), &ene_target_e );
3232 :
3233 1674000 : ene_proc = BASOP_Util_Add_Mant32Exp( hHeadTrackData->procChEneIIR_fx[0][band_idx], sub( 31, hHeadTrackData->q_procChEneIIR[0][band_idx] ), hHeadTrackData->procChEneIIR_fx[1][band_idx], sub( 31, hHeadTrackData->q_procChEneIIR[1][band_idx] ), &ene_proc_e );
3234 :
3235 1674000 : temp_div = L_deposit_h( BASOP_Util_Divide3232_Scale( ene_target, L_max( 1, ene_proc ), &e_div ) );
3236 1674000 : e_div = add( e_div, sub( ene_target_e, ene_proc_e ) );
3237 :
3238 1674000 : eqVal = Sqrt32( temp_div, &e_div );
3239 :
3240 1674000 : Word16 comp_flag = BASOP_Util_Cmp_Mant32Exp( 1073741824, 3, eqVal, e_div );
3241 1674000 : IF( EQ_16( comp_flag, -1 ) )
3242 : {
3243 321 : eqVal = 1073741824; // 4inQ28
3244 321 : move32();
3245 : }
3246 : ELSE
3247 : {
3248 1673679 : eqVal = L_shl( eqVal, sub( e_div, 3 ) ); // Q28
3249 : }
3250 :
3251 8370000 : FOR( slot = 0; slot < nSlots; slot++ )
3252 : {
3253 20088000 : FOR( ch = 0; ch < 2; ch++ )
3254 : {
3255 39312000 : FOR( bin = bin_lo; bin < bin_hi; bin++ )
3256 : {
3257 25920000 : Word16 temp_shift = s_min( norm_l( inRe_fx[ch][slot][bin] ), norm_l( inIm_fx[ch][slot][bin] ) );
3258 25920000 : re = L_shl( inRe_fx[ch][slot][bin], temp_shift );
3259 25920000 : img = L_shl( inIm_fx[ch][slot][bin], temp_shift );
3260 :
3261 25920000 : re = L_shr( Mpy_32_32( re, eqVal ), sub( temp_shift, 3 ) );
3262 25920000 : img = L_shr( Mpy_32_32( img, eqVal ), sub( temp_shift, 3 ) );
3263 25920000 : inRe_fx[ch][slot][bin] = re; // q_inp
3264 25920000 : inIm_fx[ch][slot][bin] = img; // q_inp
3265 25920000 : move32();
3266 25920000 : move32();
3267 : }
3268 : }
3269 : }
3270 : }
3271 :
3272 72000 : is_zero = 1;
3273 72000 : move16();
3274 73139 : FOR( i = 0; i < MASA_FREQUENCY_BANDS; i++ )
3275 : {
3276 73107 : test();
3277 73107 : if ( ( hHeadTrackData->chEneIIR_fx[0][i] != 0 ) || ( hHeadTrackData->chEneIIR_fx[1][i] != 0 ) )
3278 : {
3279 71968 : is_zero = 0;
3280 71968 : move16();
3281 71968 : BREAK;
3282 : }
3283 : }
3284 72000 : IF( is_zero )
3285 : {
3286 32 : set16_fx( hHeadTrackData->q_chEneIIR[0], 31, MASA_FREQUENCY_BANDS );
3287 32 : set16_fx( hHeadTrackData->q_chEneIIR[1], 31, MASA_FREQUENCY_BANDS );
3288 : }
3289 :
3290 72000 : is_zero = 1;
3291 72000 : move16();
3292 73194 : FOR( i = 0; i < MASA_FREQUENCY_BANDS; i++ )
3293 : {
3294 73162 : test();
3295 73162 : if ( ( hHeadTrackData->procChEneIIR_fx[0][i] != 0 ) || ( hHeadTrackData->procChEneIIR_fx[1][i] != 0 ) )
3296 : {
3297 71968 : is_zero = 0;
3298 71968 : move16();
3299 71968 : BREAK;
3300 : }
3301 : }
3302 72000 : IF( is_zero )
3303 : {
3304 32 : set16_fx( hHeadTrackData->q_procChEneIIR[0], 31, MASA_FREQUENCY_BANDS );
3305 32 : set16_fx( hHeadTrackData->q_procChEneIIR[1], 31, MASA_FREQUENCY_BANDS );
3306 : }
3307 :
3308 72000 : return;
3309 : }
3310 :
3311 :
3312 72000 : static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked_fx(
3313 : COMBINED_ORIENTATION_HANDLE hHeadTrackData,
3314 : Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
3315 : Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
3316 : const Word16 nBins,
3317 : const Word16 nSlots,
3318 : Word32 Rmat_fx[3][3] /*Q30*/ )
3319 : {
3320 : Word16 slot, bin, ch;
3321 : Word32 tmpVal;
3322 72000 : Word16 norm, e_div, shift = 31;
3323 72000 : move16();
3324 : Word32 Re, Im, temp_div;
3325 :
3326 : /* When not currently in prototype signal left-right switching procedure, check if such switching is needed */
3327 72000 : IF( EQ_16( hHeadTrackData->lrSwitchedNext, hHeadTrackData->lrSwitchedCurrent ) )
3328 : {
3329 65108 : Word32 thresholdDotProduct = 182536112; // 0.17 in Q30// /* Corresponds to 10-degree switching threshold */
3330 65108 : move32();
3331 65108 : test();
3332 65108 : if ( hHeadTrackData->lrSwitchedCurrent == 0 && ( LT_32( Rmat_fx[1][1], L_negate( thresholdDotProduct ) ) ) )
3333 : {
3334 38 : hHeadTrackData->lrSwitchedNext = 1;
3335 38 : move16();
3336 : }
3337 65108 : test();
3338 65108 : if ( EQ_16( hHeadTrackData->lrSwitchedCurrent, 1 ) && ( GT_32( Rmat_fx[1][1], thresholdDotProduct ) ) )
3339 : {
3340 32 : hHeadTrackData->lrSwitchedNext = 0;
3341 32 : move16();
3342 : }
3343 : }
3344 :
3345 216000 : FOR( Word16 i = 0; i < 2; i++ )
3346 : {
3347 720000 : FOR( Word16 j = 0; j < nSlots; j++ )
3348 : {
3349 576000 : norm = s_min( L_norm_arr( inRe_fx[i][j], nBins ), L_norm_arr( inIm_fx[i][j], nBins ) );
3350 576000 : shift = s_min( norm, shift );
3351 : }
3352 : }
3353 :
3354 72000 : shift = sub( shift, 3 ); // guard bits//
3355 : /* When currently in interpolation */
3356 72000 : IF( NE_16( hHeadTrackData->lrSwitchedNext, hHeadTrackData->lrSwitchedCurrent ) )
3357 : {
3358 34810 : FOR( slot = 0; slot < nSlots; slot++ )
3359 : {
3360 : Word32 switchOrderFactor, origOrderFactor;
3361 : Word16 e_switchOrderFactor, e_origOrderFactor;
3362 :
3363 27848 : hHeadTrackData->lrSwitchInterpVal_fx = L_add( hHeadTrackData->lrSwitchInterpVal_fx, 2684354 /* 0.0025f in Q30 */ ); /* Corresponds to 0.5 seconds interpolation time */ /* Q30 */
3364 27848 : move32();
3365 :
3366 27848 : IF( GT_32( hHeadTrackData->lrSwitchInterpVal_fx, 1072668096 /* 0.999f in Q30 */ ) )
3367 : {
3368 : /* Stop interpolation, reset values */
3369 68 : hHeadTrackData->lrSwitchInterpVal_fx = 0;
3370 68 : hHeadTrackData->lrSwitchedCurrent = hHeadTrackData->lrSwitchedNext;
3371 68 : move32();
3372 68 : move16();
3373 : }
3374 :
3375 : /* Gains for determining portion of switched channel order and original channel order */
3376 27848 : tmpVal = Mpy_32_16_1( hHeadTrackData->lrSwitchInterpVal_fx, (Word16) hHeadTrackData->lrSwitchedNext ); /* Q15 */
3377 27848 : tmpVal = L_add( tmpVal, Mpy_32_16_1( L_sub( ONE_IN_Q30, hHeadTrackData->lrSwitchInterpVal_fx ), (Word16) hHeadTrackData->lrSwitchedCurrent ) ); /* Q15 */
3378 :
3379 27848 : e_switchOrderFactor = 0;
3380 27848 : e_origOrderFactor = 0;
3381 27848 : move16();
3382 27848 : move16();
3383 27848 : IF( EQ_32( tmpVal, 32768 ) )
3384 : {
3385 38 : tmpVal = ONE_IN_Q31;
3386 38 : move32();
3387 : }
3388 : ELSE
3389 27810 : tmpVal = L_shl( tmpVal, 16 ); // Q31
3390 27848 : switchOrderFactor = Sqrt32( tmpVal, &e_switchOrderFactor );
3391 27848 : switchOrderFactor = L_shl( switchOrderFactor, e_switchOrderFactor ); // Q31
3392 27848 : origOrderFactor = Sqrt32( L_sub( ONE_IN_Q31, tmpVal ), &e_origOrderFactor ); // Q31
3393 27848 : origOrderFactor = L_shl( origOrderFactor, e_origOrderFactor );
3394 1298728 : FOR( bin = 0; bin < nBins; bin++ )
3395 : {
3396 : /* determine original order (1) signals and switched order (2) signals */
3397 : Word32 re1[BINAURAL_CHANNELS], re2[BINAURAL_CHANNELS], im1[BINAURAL_CHANNELS], im2[BINAURAL_CHANNELS];
3398 :
3399 3812640 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
3400 : {
3401 2541760 : re1[ch] = Mpy_32_32( inRe_fx[ch][slot][bin], origOrderFactor ); // q_inp
3402 2541760 : re2[ch] = Mpy_32_32( inRe_fx[1 - ch][slot][bin], switchOrderFactor ); // q_inp
3403 2541760 : im1[ch] = Mpy_32_32( inIm_fx[ch][slot][bin], origOrderFactor ); // q_inp
3404 2541760 : im2[ch] = Mpy_32_32( inIm_fx[1 - ch][slot][bin], switchOrderFactor ); // q_inp
3405 2541760 : move32();
3406 2541760 : move32();
3407 2541760 : move32();
3408 2541760 : move32();
3409 : }
3410 :
3411 3812640 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
3412 : {
3413 : Word32 eneRef, ene, eq;
3414 :
3415 2541760 : re1[ch] = L_shl( re1[ch], shift ); // q_inp+shift//
3416 2541760 : re2[ch] = L_shl( re2[ch], shift ); // q_inp+shift//
3417 2541760 : im1[ch] = L_shl( im1[ch], shift ); // q_inp+shift//
3418 2541760 : im2[ch] = L_shl( im2[ch], shift ); // q_inp+shift//
3419 2541760 : move32();
3420 2541760 : move32();
3421 2541760 : move32();
3422 2541760 : move32();
3423 :
3424 : /* Interpolate / mix original and switched order signals */
3425 2541760 : Re = L_add( re1[ch], re2[ch] ); // q_inp+shift//
3426 2541760 : Im = L_add( im1[ch], im2[ch] ); // q_inp+shift//
3427 :
3428 : /* Equalize interpolated signals to preserve energy per bin */
3429 :
3430 2541760 : eneRef = L_add( ( L_add( Mpy_32_32( re1[ch], re1[ch] ), Mpy_32_32( re2[ch], re2[ch] ) ) ), ( L_add( Mpy_32_32( im1[ch], im1[ch] ), Mpy_32_32( im2[ch], im2[ch] ) ) ) ); // 2*(q_inp+shift) -31//
3431 2541760 : ene = L_add( Mpy_32_32( Re, Re ), Mpy_32_32( Im, Im ) ); // 2*(q_inp+shift) -31//
3432 :
3433 2541760 : temp_div = L_deposit_h( BASOP_Util_Divide3232_Scale( eneRef, L_max( 1, ene ), &e_div ) );
3434 :
3435 2541760 : eq = Sqrt32( temp_div, &e_div );
3436 :
3437 2541760 : Word16 comp_flag = BASOP_Util_Cmp_Mant32Exp( 1073741824, 3, eq, e_div );
3438 2541760 : IF( EQ_16( comp_flag, -1 ) )
3439 : {
3440 15385 : eq = 1073741824; // 4inQ28
3441 15385 : move32();
3442 : }
3443 : ELSE
3444 : {
3445 2526375 : eq = L_shl( eq, sub( e_div, 3 ) ); // Q28
3446 : }
3447 :
3448 2541760 : Re = L_shr( Mpy_32_32( Re, eq ), sub( shift, 3 ) ); // q_inp
3449 2541760 : Im = L_shr( Mpy_32_32( Im, eq ), sub( shift, 3 ) ); // q_inp
3450 :
3451 2541760 : inRe_fx[ch][slot][bin] = Re;
3452 2541760 : inIm_fx[ch][slot][bin] = Im;
3453 2541760 : move32();
3454 2541760 : move32();
3455 : }
3456 : }
3457 : }
3458 : }
3459 : ELSE
3460 : {
3461 : /* If not in interpolation, but in switched prototype situation, then switch left and right channels */
3462 65038 : IF( EQ_16( hHeadTrackData->lrSwitchedCurrent, 1 ) )
3463 : {
3464 37425 : FOR( slot = 0; slot < nSlots; slot++ )
3465 : {
3466 1333140 : FOR( bin = 0; bin < nBins; bin++ )
3467 : {
3468 1303200 : tmpVal = inRe_fx[0][slot][bin];
3469 1303200 : inRe_fx[0][slot][bin] = inRe_fx[1][slot][bin];
3470 1303200 : inRe_fx[1][slot][bin] = tmpVal;
3471 1303200 : tmpVal = inIm_fx[0][slot][bin];
3472 1303200 : inIm_fx[0][slot][bin] = inIm_fx[1][slot][bin];
3473 1303200 : inIm_fx[1][slot][bin] = tmpVal;
3474 1303200 : move32();
3475 1303200 : move32();
3476 1303200 : move32();
3477 1303200 : move32();
3478 : }
3479 : }
3480 : }
3481 : }
3482 :
3483 72000 : return;
3484 : }
3485 :
3486 :
3487 42829130 : static void eig2x2_fx(
3488 : const Word32 E1_fx, /*q_E*/
3489 : const Word32 E2_fx, /*q_E*/
3490 : Word16 q_E,
3491 : const Word32 Cre_fx, /*q_C*/
3492 : const Word32 Cim_fx, /*q_C*/
3493 : Word16 q_C,
3494 : Word32 Ure_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_U*/
3495 : Word32 Uim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_U*/
3496 : Word16 *q_U,
3497 : Word32 D_fx[BINAURAL_CHANNELS], /*q_D*/
3498 : Word16 *q_D )
3499 : {
3500 : Word16 chA, chB, ch;
3501 : Word32 s_fx, normVal_fx, crossSquare_fx, a_fx, pm_fx, add_fx;
3502 : Word32 tmp1, tmp2, tmp3, e1, e2, c_re, c_im;
3503 : Word16 q_crossSquare, q_tmp1, q_tmp2, exp_tmp3, exp, q_e, q_c, q_U_1, q_U_2;
3504 42829130 : Word32 epsilon_mant = 1180591621;
3505 42829130 : Word16 epsilon_exp = -39;
3506 42829130 : move32();
3507 42829130 : move16();
3508 :
3509 42829130 : pm_fx = 0;
3510 42829130 : move32();
3511 42829130 : add_fx = 0;
3512 42829130 : move32();
3513 42829130 : q_tmp2 = 0;
3514 42829130 : move16();
3515 :
3516 128487390 : FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
3517 : {
3518 256974780 : FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
3519 : {
3520 171316520 : Ure_fx[chA][chB] = 0;
3521 171316520 : move32();
3522 171316520 : Uim_fx[chA][chB] = 0;
3523 171316520 : move32();
3524 : }
3525 : }
3526 :
3527 42829130 : exp = sub( get_min_scalefactor( Cre_fx, Cim_fx ), 2 );
3528 42829130 : c_re = L_shl( Cre_fx, exp );
3529 42829130 : c_im = L_shl( Cim_fx, exp );
3530 42829130 : q_c = add( q_C, exp );
3531 :
3532 42829130 : exp = sub( get_min_scalefactor( E1_fx, E2_fx ), 2 );
3533 42829130 : e1 = L_shl( E1_fx, exp );
3534 42829130 : e2 = L_shl( E2_fx, exp );
3535 42829130 : q_e = add( q_E, exp );
3536 :
3537 : /*crossSquare_fx = (c_re * c_re) + (c_im * c_im)
3538 : a_fx = (e1 + e2) * (e1 + e2) - 4.0f * ((e1 * e2) - crossSquare_fx) = (e1 - e2)^2 + 4 * crossSquare_fx
3539 : pm_fx = 0.5f * sqrtf(max(0.0f, a_fx))
3540 : add_fx = 0.5f * (e1 + e2)*/
3541 :
3542 42829130 : IF( L_and( c_re == 0, c_im == 0 ) )
3543 : {
3544 : /* if c_re = 0 and c_im = 0, then crossSquare_fx = (c_re * c_re) + (c_im * c_im) = 0
3545 : a_fx = (E1 - E2)^2
3546 : pm_fx = 0.5 * sqrt(max(0, a_fx)) = 0.5 * max(0, (e1 - e2)) */
3547 11844223 : crossSquare_fx = 0;
3548 11844223 : move32();
3549 11844223 : q_crossSquare = Q31;
3550 11844223 : move16();
3551 11844223 : pm_fx = L_shr( L_max( 0, L_abs( L_sub( e1, e2 ) ) ), 1 );
3552 11844223 : q_tmp2 = q_e;
3553 11844223 : move16();
3554 : }
3555 : ELSE
3556 : {
3557 30984907 : crossSquare_fx = Madd_32_32( Mpy_32_32( c_re, c_re ), c_im, c_im );
3558 30984907 : q_crossSquare = sub( add( q_c, q_c ), 31 );
3559 30984907 : IF( EQ_32( e1, e2 ) )
3560 : {
3561 : /* if e1 - e2 = 0, then a_fx = 4 * crossSquare_fx
3562 : pm_fx = 0.5 * sqrt(max(0, 4 * crossSquare_fx)) = sqrt(0, crossSquare_fx)*/
3563 4290447 : test();
3564 4290447 : test();
3565 4290447 : IF( EQ_32( c_re, 0 ) || LT_32( L_abs( c_re ), ONE_IN_Q15 ) )
3566 : {
3567 : /* if c_re = 0, then crossSquare_fx = c_im^2 => pm_fx = max(0, c_im) */
3568 8634 : pm_fx = L_max( 0, L_abs( c_im ) );
3569 8634 : q_tmp2 = q_c;
3570 8634 : move16();
3571 : }
3572 4281813 : ELSE IF( c_im == 0 || LT_32( L_abs( c_im ), ONE_IN_Q15 ) )
3573 : {
3574 : /* if c_im = 0, then crossSquare_fx = c_re^2 => pm_fx = max(0, c_re) */
3575 4246238 : pm_fx = L_max( 0, L_abs( c_re ) );
3576 4246238 : q_tmp2 = q_c;
3577 4246238 : move16();
3578 : }
3579 : ELSE
3580 : {
3581 35575 : exp = sub( 31, q_crossSquare );
3582 35575 : pm_fx = Sqrt32( L_max( 0, crossSquare_fx ), &exp );
3583 35575 : q_tmp2 = sub( 31, exp );
3584 : }
3585 : }
3586 : ELSE
3587 : {
3588 : /* if e1, e2 >> c_re, c_im then (e1 - e2)^2 ~ (e1 - e2)^2 + 4 * crossSquare_fx
3589 : a_fx = (E1 - E2)^2
3590 : pm_fx = 0.5 * sqrt(max(0, a_fx)) = 0.5 * max(0, (e1 - e2)) */
3591 :
3592 26694460 : IF( GT_16( sub( q_c, q_e ), Q15 ) )
3593 : {
3594 26962 : pm_fx = L_shr( L_max( 0, L_abs( L_sub( e1, e2 ) ) ), 1 );
3595 26962 : q_tmp2 = q_e;
3596 26962 : move16();
3597 : }
3598 : ELSE
3599 : {
3600 26667498 : tmp2 = crossSquare_fx;
3601 26667498 : move32();
3602 26667498 : q_tmp2 = sub( q_crossSquare, 2 ); // crossSquare_fx = 4 * crossSquare_fx;
3603 :
3604 26667498 : tmp1 = Mpy_32_32( L_sub( e1, e2 ), L_sub( e1, e2 ) );
3605 26667498 : q_tmp1 = sub( add( q_e, q_e ), 31 );
3606 :
3607 26667498 : a_fx = BASOP_Util_Add_Mant32Exp( tmp1, sub( 31, q_tmp1 ), tmp2, sub( 31, q_tmp2 ), &q_tmp2 ); // (E1 - E2)^2 + 4 * crossSquare_fx
3608 26667498 : q_tmp2 = sub( 31, q_tmp2 );
3609 :
3610 26667498 : exp = sub( 31, q_tmp2 );
3611 26667498 : pm_fx = Sqrt32( L_max( 0, L_sub( a_fx, 1 ) ), &exp );
3612 26667498 : pm_fx = L_shr( pm_fx, 1 );
3613 26667498 : q_tmp2 = sub( 31, exp );
3614 : }
3615 : }
3616 : }
3617 : // add_fx = 0.5 * (e1 + e2)
3618 42829130 : add_fx = L_shr( L_add( e1, e2 ), 1 );
3619 42829130 : q_tmp1 = q_e;
3620 42829130 : move16();
3621 :
3622 42829130 : IF( LT_16( q_tmp1, q_tmp2 ) )
3623 : {
3624 26760078 : D_fx[0] = L_add( L_shr( add_fx, 1 ), L_shr( pm_fx, add( sub( q_tmp2, q_tmp1 ), 1 ) ) );
3625 26760078 : move32();
3626 26760078 : D_fx[1] = L_max( 0, L_sub( L_shr( add_fx, 1 ), L_shr( pm_fx, add( sub( q_tmp2, q_tmp1 ), 1 ) ) ) );
3627 26760078 : move32();
3628 26760078 : *q_D = sub( q_tmp1, 1 );
3629 26760078 : move16();
3630 : }
3631 : ELSE
3632 : {
3633 16069052 : D_fx[0] = L_add( L_shr( add_fx, add( sub( q_tmp1, q_tmp2 ), 1 ) ), L_shr( pm_fx, 1 ) );
3634 16069052 : move32();
3635 16069052 : D_fx[1] = L_max( 0, L_sub( L_shr( add_fx, add( sub( q_tmp1, q_tmp2 ), 1 ) ), L_shr( pm_fx, 1 ) ) );
3636 16069052 : move32();
3637 16069052 : *q_D = sub( q_tmp2, 1 );
3638 16069052 : move16();
3639 : }
3640 :
3641 : /* Numeric case, when input is practically zeros */
3642 : // IF( D_fx[0] < EPSILON_FX )
3643 :
3644 42829130 : IF( LT_32( L_shl_sat( D_fx[0], sub( sub( 31, *q_D ), EPSILON_EXP ) ), EPSILON_MANT ) )
3645 : {
3646 216883 : Ure_fx[0][0] = ONE_IN_Q31;
3647 216883 : move32();
3648 216883 : Ure_fx[1][1] = ONE_IN_Q31;
3649 216883 : move32();
3650 216883 : *q_U = Q31;
3651 216883 : move16();
3652 :
3653 216883 : return;
3654 : }
3655 :
3656 : /* Numeric case, when input is near an identity matrix with a gain */
3657 42612247 : tmp1 = Mpy_32_32( 2147484, add_fx ); // 2147484 = 1e-3f in Q31
3658 :
3659 42612247 : IF( LT_16( q_tmp1, q_tmp2 ) )
3660 : {
3661 26682718 : IF( LT_32( L_shr( pm_fx, sub( q_tmp2, q_tmp1 ) ), tmp1 ) )
3662 : {
3663 0 : Ure_fx[0][0] = ONE_IN_Q30;
3664 0 : move32();
3665 0 : Ure_fx[1][1] = ONE_IN_Q30;
3666 0 : move32();
3667 0 : *q_U = Q30;
3668 0 : move16();
3669 :
3670 0 : return;
3671 : }
3672 : }
3673 : ELSE
3674 : {
3675 15929529 : IF( LT_32( pm_fx, L_shr( tmp1, sub( q_tmp1, q_tmp2 ) ) ) )
3676 : {
3677 4060974 : Ure_fx[0][0] = ONE_IN_Q30;
3678 4060974 : move32();
3679 4060974 : Ure_fx[1][1] = ONE_IN_Q30;
3680 4060974 : move32();
3681 4060974 : *q_U = Q30;
3682 4060974 : move16();
3683 :
3684 4060974 : return;
3685 : }
3686 : }
3687 :
3688 38551273 : q_U_1 = 0;
3689 38551273 : q_U_2 = 0;
3690 38551273 : move16();
3691 38551273 : move16();
3692 :
3693 : /* Eigenvectors */
3694 115653819 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
3695 : {
3696 77102546 : Word16 q_diff = sub( q_e, *q_D );
3697 77102546 : IF( q_diff > 0 )
3698 : {
3699 77102546 : tmp1 = L_sub( D_fx[ch], L_shr( e1, q_diff ) );
3700 77102546 : tmp2 = L_sub( D_fx[ch], L_shr( e2, q_diff ) );
3701 77102546 : q_tmp1 = *q_D;
3702 77102546 : move16();
3703 : }
3704 : ELSE
3705 : {
3706 0 : tmp1 = L_sub( L_shl( D_fx[ch], q_diff ), e1 );
3707 0 : tmp2 = L_sub( L_shl( D_fx[ch], q_diff ), e2 );
3708 0 : q_tmp1 = q_e;
3709 0 : move16();
3710 : }
3711 :
3712 77102546 : IF( GT_32( L_abs( tmp2 ), L_abs( tmp1 ) ) )
3713 : {
3714 34335740 : s_fx = tmp2;
3715 34335740 : move32();
3716 34335740 : exp = sub( norm_l( s_fx ), 1 );
3717 34335740 : tmp2 = Mpy_32_32( s_fx, s_fx );
3718 34335740 : q_tmp2 = sub( add( q_tmp1, q_tmp1 ), 31 );
3719 :
3720 34335740 : tmp2 = BASOP_Util_Add_Mant32Exp( crossSquare_fx, sub( 31, q_crossSquare ), tmp2, sub( 31, q_tmp2 ), &q_tmp2 );
3721 34335740 : q_tmp2 = sub( 31, q_tmp2 );
3722 :
3723 34335740 : tmp3 = BASOP_Util_Add_Mant32Exp( tmp2, sub( 31, q_tmp2 ), epsilon_mant, epsilon_exp, &exp_tmp3 );
3724 :
3725 34335740 : tmp2 = BASOP_Util_Divide3232_Scale_newton( ONE_IN_Q30, tmp3, &exp );
3726 34335740 : exp = sub( exp, sub( Q30, sub( 31, exp_tmp3 ) ) );
3727 34335740 : normVal_fx = Sqrt32( tmp2, &exp ); // q_tmp2
3728 34335740 : q_tmp2 = sub( 31, exp );
3729 :
3730 34335740 : q_diff = sub( q_c, q_tmp1 );
3731 34335740 : IF( q_diff > 0 )
3732 : {
3733 16128007 : c_re = L_shr( c_re, q_diff );
3734 16128007 : c_im = L_shr( c_im, q_diff );
3735 16128007 : q_c = q_tmp1;
3736 16128007 : move16();
3737 : }
3738 : ELSE
3739 : {
3740 18207733 : s_fx = L_shl( s_fx, q_diff );
3741 18207733 : q_tmp1 = q_c;
3742 18207733 : move16();
3743 : }
3744 :
3745 34335740 : Ure_fx[0][ch] = Mpy_32_32( s_fx, normVal_fx );
3746 34335740 : move32();
3747 34335740 : Ure_fx[1][ch] = Mpy_32_32( c_re, normVal_fx );
3748 34335740 : move32();
3749 34335740 : Uim_fx[1][ch] = Mpy_32_32( c_im, normVal_fx );
3750 34335740 : move32();
3751 34335740 : q_U_1 = sub( add( q_tmp1, q_tmp2 ), 31 );
3752 :
3753 34335740 : IF( q_U_2 != 0 )
3754 : {
3755 14001817 : q_diff = sub( q_U_2, q_U_1 );
3756 14001817 : IF( q_diff > 0 )
3757 : {
3758 1 : Ure_fx[1][ch - 1] = L_shr( Ure_fx[1][ch - 1], q_diff );
3759 1 : Ure_fx[0][ch - 1] = L_shr( Ure_fx[0][ch - 1], q_diff );
3760 1 : Uim_fx[0][ch - 1] = L_shr( Uim_fx[0][ch - 1], q_diff );
3761 1 : q_U_2 = q_U_1;
3762 1 : move32();
3763 1 : move32();
3764 1 : move32();
3765 1 : move16();
3766 : }
3767 14001816 : ELSE IF( GT_16( q_U_1, q_U_2 ) )
3768 : {
3769 0 : Ure_fx[1][ch] = L_shl( Ure_fx[1][ch], q_diff );
3770 0 : Ure_fx[0][ch] = L_shl( Ure_fx[0][ch], q_diff );
3771 0 : Uim_fx[1][ch] = L_shl( Uim_fx[1][ch], q_diff );
3772 0 : q_U_1 = q_U_2;
3773 0 : move32();
3774 0 : move32();
3775 0 : move32();
3776 0 : move16();
3777 : }
3778 : }
3779 34335740 : q_U_2 = q_U_1;
3780 34335740 : move16();
3781 : }
3782 : ELSE
3783 : {
3784 42766806 : s_fx = tmp1;
3785 42766806 : move32();
3786 :
3787 42766806 : exp = sub( norm_l( s_fx ), 1 );
3788 42766806 : tmp2 = Mpy_32_32( s_fx, s_fx );
3789 42766806 : q_tmp2 = sub( add( q_tmp1, q_tmp1 ), 31 );
3790 :
3791 42766806 : tmp2 = BASOP_Util_Add_Mant32Exp( crossSquare_fx, sub( 31, q_crossSquare ), tmp2, sub( 31, q_tmp2 ), &q_tmp2 );
3792 42766806 : q_tmp2 = sub( 31, q_tmp2 );
3793 :
3794 42766806 : tmp3 = BASOP_Util_Add_Mant32Exp( tmp2, sub( 31, q_tmp2 ), epsilon_mant, epsilon_exp, &exp_tmp3 );
3795 :
3796 42766806 : tmp2 = BASOP_Util_Divide3232_Scale_newton( ONE_IN_Q30, tmp3, &exp );
3797 42766806 : exp = sub( exp, sub( Q30, sub( 31, exp_tmp3 ) ) );
3798 42766806 : normVal_fx = Sqrt32( tmp2, &exp ); // q_tmp2
3799 42766806 : q_tmp2 = sub( 31, exp );
3800 :
3801 42766806 : q_diff = sub( q_c, q_tmp1 );
3802 42766806 : IF( q_diff > 0 )
3803 : {
3804 18213306 : c_re = L_shr( c_re, q_diff );
3805 18213306 : c_im = L_shr( c_im, q_diff );
3806 18213306 : q_c = q_tmp1;
3807 18213306 : move16();
3808 : }
3809 : ELSE
3810 : {
3811 24553500 : s_fx = L_shl( s_fx, q_diff );
3812 24553500 : q_tmp1 = q_c;
3813 24553500 : move16();
3814 : }
3815 :
3816 42766806 : Ure_fx[1][ch] = Mpy_32_32( s_fx, normVal_fx );
3817 42766806 : move32();
3818 42766806 : Ure_fx[0][ch] = Mpy_32_32( c_re, normVal_fx );
3819 42766806 : move32();
3820 42766806 : Uim_fx[0][ch] = Mpy_32_32( L_negate( c_im ), normVal_fx );
3821 42766806 : move32();
3822 42766806 : q_U_2 = sub( add( q_tmp1, q_tmp2 ), 31 );
3823 :
3824 42766806 : IF( q_U_1 != 0 )
3825 : {
3826 24549456 : q_diff = sub( q_U_2, q_U_1 );
3827 24549456 : IF( q_diff > 0 )
3828 : {
3829 0 : Ure_fx[1][ch] = L_shr( Ure_fx[1][ch], q_diff );
3830 0 : Ure_fx[0][ch] = L_shr( Ure_fx[0][ch], q_diff );
3831 0 : Uim_fx[0][ch] = L_shr( Uim_fx[0][ch], q_diff );
3832 0 : q_U_2 = q_U_1;
3833 0 : move32();
3834 0 : move32();
3835 0 : move32();
3836 0 : move16();
3837 : }
3838 24549456 : ELSE IF( GT_16( q_U_1, q_U_2 ) )
3839 : {
3840 2 : Ure_fx[1][ch - 1] = L_shl( Ure_fx[1][ch - 1], q_diff );
3841 2 : Ure_fx[0][ch - 1] = L_shl( Ure_fx[0][ch - 1], q_diff );
3842 2 : Uim_fx[1][ch - 1] = L_shl( Uim_fx[1][ch - 1], q_diff );
3843 2 : q_U_1 = q_U_2;
3844 2 : move32();
3845 2 : move32();
3846 2 : move32();
3847 2 : move16();
3848 : }
3849 : }
3850 42766806 : q_U_1 = q_U_2;
3851 42766806 : move16();
3852 : }
3853 : }
3854 :
3855 38551273 : if ( q_U_1 != 0 )
3856 : {
3857 38551273 : *q_U = q_U_1;
3858 38551273 : move16();
3859 : }
3860 :
3861 38551273 : if ( q_U_1 == 0 )
3862 : {
3863 0 : *q_U = q_U_2;
3864 0 : move16();
3865 : }
3866 :
3867 38551273 : return;
3868 : }
3869 :
3870 21414565 : static void matrixDiagMul_fx(
3871 : Word32 reIn_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_In*/
3872 : Word32 imIn_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_In*/
3873 : Word16 q_In,
3874 : const Word32 D_fx[BINAURAL_CHANNELS], /*q_D*/
3875 : Word16 q_D,
3876 : Word32 reOut_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_Out*/
3877 : Word32 imOut_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_Out*/
3878 : Word16 *q_Out )
3879 : {
3880 : Word16 chA, chB;
3881 21414565 : Word16 size = i_mult( BINAURAL_CHANNELS, BINAURAL_CHANNELS );
3882 :
3883 64243695 : FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
3884 : {
3885 128487390 : FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
3886 : {
3887 85658260 : reOut_fx[chA][chB] = Mpy_32_32( reIn_fx[chA][chB], D_fx[chB] );
3888 85658260 : imOut_fx[chA][chB] = Mpy_32_32( imIn_fx[chA][chB], D_fx[chB] );
3889 85658260 : move32();
3890 85658260 : move32();
3891 : }
3892 : }
3893 :
3894 21414565 : *q_Out = sub( add( q_In, q_D ), 31 );
3895 21414565 : move16();
3896 :
3897 21414565 : if ( L_and( is_zero_arr( reOut_fx[0], size ), is_zero_arr( imOut_fx[0], size ) ) )
3898 : {
3899 48892 : *q_Out = Q31;
3900 48892 : move16();
3901 : }
3902 :
3903 21414565 : return;
3904 : }
3905 :
3906 78162115 : static void matrixMul_fx(
3907 : Word32 Are_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_A*/
3908 : Word32 Aim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_A*/
3909 : Word16 *q_A,
3910 : Word32 Bre_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_B*/
3911 : Word32 Bim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_B*/
3912 : Word16 *q_B,
3913 : Word32 outRe_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_out*/
3914 : Word32 outIm_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_out*/
3915 : Word16 *q_out )
3916 : {
3917 : Word16 chA, chB;
3918 : Word16 min_q_shift1, min_q_shift2;
3919 78162115 : Word16 size = i_mult( BINAURAL_CHANNELS, BINAURAL_CHANNELS );
3920 :
3921 78162115 : min_q_shift1 = sub( s_min( L_norm_arr( Are_fx[0], size ), L_norm_arr( Aim_fx[0], size ) ), 1 );
3922 78162115 : min_q_shift2 = sub( s_min( L_norm_arr( Bre_fx[0], size ), L_norm_arr( Bim_fx[0], size ) ), 1 );
3923 :
3924 78162115 : scale_sig32( Are_fx[0], size, min_q_shift1 );
3925 78162115 : scale_sig32( Aim_fx[0], size, min_q_shift1 );
3926 78162115 : scale_sig32( Bre_fx[0], size, min_q_shift2 );
3927 78162115 : scale_sig32( Bim_fx[0], size, min_q_shift2 );
3928 :
3929 78162115 : *q_A = add( *q_A, min_q_shift1 );
3930 78162115 : *q_B = add( *q_B, min_q_shift2 );
3931 78162115 : move16();
3932 78162115 : move16();
3933 :
3934 234486345 : FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
3935 : {
3936 468972690 : FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
3937 : {
3938 : #ifdef IVAS_ENH64_CADENCE_CHANGES
3939 : outRe_fx[chA][chB] = W_extract_h( W_mac_32_32( W_mult_32_32( Are_fx[chA][0], Bre_fx[0][chB] ), Are_fx[chA][1], Bre_fx[1][chB] ) );
3940 : move32();
3941 : outRe_fx[chA][chB] = L_sub( outRe_fx[chA][chB], W_extract_h( W_mac_32_32( W_mult_32_32( Aim_fx[chA][0], Bim_fx[0][chB] ), Aim_fx[chA][1], Bim_fx[1][chB] ) ) );
3942 : move32();
3943 : outIm_fx[chA][chB] = W_extract_h( W_mac_32_32( W_mult_32_32( Aim_fx[chA][0], Bre_fx[0][chB] ), Aim_fx[chA][1], Bre_fx[1][chB] ) );
3944 : move32();
3945 : outIm_fx[chA][chB] = L_add( outIm_fx[chA][chB], W_extract_h( W_mac_32_32( W_mult_32_32( Are_fx[chA][0], Bim_fx[0][chB] ), Are_fx[chA][1], Bim_fx[1][chB] ) ) );
3946 : move32();
3947 : #else
3948 312648460 : outRe_fx[chA][chB] = Msub_32_32( Msub_32_32( Madd_32_32( Mpy_32_32( Are_fx[chA][0], Bre_fx[0][chB] ),
3949 312648460 : Are_fx[chA][1], Bre_fx[1][chB] ),
3950 312648460 : Aim_fx[chA][0], Bim_fx[0][chB] ),
3951 312648460 : Aim_fx[chA][1], Bim_fx[1][chB] );
3952 312648460 : move32();
3953 312648460 : outIm_fx[chA][chB] = Madd_32_32( Madd_32_32( Madd_32_32( Mpy_32_32( Aim_fx[chA][0], Bre_fx[0][chB] ),
3954 312648460 : Aim_fx[chA][1], Bre_fx[1][chB] ),
3955 312648460 : Are_fx[chA][0], Bim_fx[0][chB] ),
3956 312648460 : Are_fx[chA][1], Bim_fx[1][chB] );
3957 312648460 : move32();
3958 : #endif /* #ifdef IVAS_ENH64_CADENCE_CHANGES */
3959 : }
3960 : }
3961 78162115 : *q_out = sub( add( *q_A, *q_B ), 31 );
3962 :
3963 78162115 : move16();
3964 78162115 : if ( L_and( is_zero_arr( outRe_fx[0], size ), is_zero_arr( outIm_fx[0], size ) ) )
3965 : {
3966 287100 : *q_out = Q31;
3967 287100 : move16();
3968 : }
3969 :
3970 78162115 : return;
3971 : }
3972 :
3973 21414565 : static void matrixTransp1Mul_fx(
3974 : Word32 Are_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_A*/
3975 : Word32 Aim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_A*/
3976 : Word16 q_A,
3977 : Word32 Bre_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_B*/
3978 : Word32 Bim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_B*/
3979 : Word16 q_B,
3980 : Word32 outRe_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_out*/
3981 : Word32 outIm_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_out*/
3982 : Word16 *q_out )
3983 : {
3984 : Word16 chA, chB;
3985 21414565 : Word16 size = i_mult( BINAURAL_CHANNELS, BINAURAL_CHANNELS );
3986 :
3987 : Word64 tmp_outRe_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
3988 : Word64 tmp_outIm_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
3989 : Word16 q_tmp_outRe_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
3990 : Word16 q_tmp_outIm_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
3991 : Word64 tmp64_1, tmp64_2;
3992 21414565 : Word16 tmp16, q_common = 63;
3993 21414565 : move16();
3994 :
3995 64243695 : FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
3996 : {
3997 128487390 : FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
3998 : {
3999 85658260 : tmp64_1 = W_mac_32_32( W_mult_32_32( Are_fx[0][chA], Bre_fx[0][chB] ), Are_fx[1][chA], Bre_fx[1][chB] ); // Q: add( add( q_A, q_B ), 1 )
4000 85658260 : tmp64_2 = W_mac_32_32( W_mult_32_32( Aim_fx[0][chA], Bim_fx[0][chB] ), Aim_fx[1][chA], Bim_fx[1][chB] ); // Q: add( add( q_A, q_B ), 1 )
4001 85658260 : tmp_outRe_fx[chA][chB] = W_add( tmp64_1, tmp64_2 ); // Q: add( add( q_A, q_B ), 1 )
4002 85658260 : move64();
4003 85658260 : tmp16 = W_norm( tmp_outRe_fx[chA][chB] );
4004 85658260 : tmp_outRe_fx[chA][chB] = W_shl( tmp_outRe_fx[chA][chB], tmp16 ); // Q:add( tmp16, add( add( q_A, q_B ), 1 ) )
4005 85658260 : move64();
4006 85658260 : q_tmp_outRe_fx[chA][chB] = add( tmp16, add( add( q_A, q_B ), 1 ) );
4007 85658260 : move16();
4008 85658260 : q_common = s_min( q_tmp_outRe_fx[chA][chB], q_common );
4009 :
4010 :
4011 85658260 : tmp64_1 = W_mac_32_32( W_mult_32_32( Are_fx[0][chA], Bim_fx[0][chB] ), Are_fx[1][chA], Bim_fx[1][chB] ); // Q: add( add( q_A, q_B ), 1 )
4012 85658260 : tmp64_2 = W_mac_32_32( W_mult_32_32( Aim_fx[0][chA], Bre_fx[0][chB] ), Aim_fx[1][chA], Bre_fx[1][chB] ); // Q: add( add( q_A, q_B ), 1 )
4013 85658260 : tmp_outIm_fx[chA][chB] = W_sub( tmp64_1, tmp64_2 ); // Q: add( add( q_A, q_B ), 1 )
4014 85658260 : move64();
4015 85658260 : tmp16 = W_norm( tmp_outIm_fx[chA][chB] );
4016 85658260 : tmp_outIm_fx[chA][chB] = W_shl( tmp_outIm_fx[chA][chB], tmp16 ); // Q:add( tmp16, add( add( q_A, q_B ), 1 ) )
4017 85658260 : move64();
4018 85658260 : q_tmp_outIm_fx[chA][chB] = add( tmp16, add( add( q_A, q_B ), 1 ) );
4019 85658260 : move16();
4020 85658260 : q_common = s_min( q_tmp_outIm_fx[chA][chB], q_common );
4021 : }
4022 : }
4023 64243695 : FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
4024 : {
4025 128487390 : FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
4026 : {
4027 : #ifdef FIX_ISSUE_1811_EXCEEDING_W_SHIFTS
4028 85658260 : outRe_fx[chA][chB] = W_extract_h( W_shl( tmp_outRe_fx[chA][chB], s_max( -63, sub( q_common, q_tmp_outRe_fx[chA][chB] ) ) ) );
4029 85658260 : move32();
4030 85658260 : outIm_fx[chA][chB] = W_extract_h( W_shl( tmp_outIm_fx[chA][chB], s_max( -63, sub( q_common, q_tmp_outIm_fx[chA][chB] ) ) ) );
4031 85658260 : move32();
4032 : #else
4033 : outRe_fx[chA][chB] = W_extract_h( W_shl( tmp_outRe_fx[chA][chB], sub( q_common, q_tmp_outRe_fx[chA][chB] ) ) );
4034 : move32();
4035 : outIm_fx[chA][chB] = W_extract_h( W_shl( tmp_outIm_fx[chA][chB], sub( q_common, q_tmp_outIm_fx[chA][chB] ) ) );
4036 : move32();
4037 : #endif
4038 : }
4039 : }
4040 21414565 : *q_out = sub( q_common, 32 );
4041 21414565 : move16();
4042 21414565 : if ( L_and( is_zero_arr( outRe_fx[0], size ), is_zero_arr( outIm_fx[0], size ) ) )
4043 : {
4044 82811 : *q_out = Q31;
4045 82811 : move16();
4046 : }
4047 :
4048 21414565 : return;
4049 : }
4050 :
4051 56747550 : static void matrixTransp2Mul_fx(
4052 : Word32 Are_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_A*/
4053 : Word32 Aim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_A*/
4054 : Word16 *q_A,
4055 : Word32 Bre_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_B*/
4056 : Word32 Bim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_B*/
4057 : Word16 *q_B,
4058 : Word32 Ascale,
4059 : Word32 Bscale,
4060 : Word32 outRe_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_out*/
4061 : Word32 outIm_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_out*/
4062 : Word16 *q_out )
4063 : {
4064 : Word16 chA, chB;
4065 : Word16 min_q_shift;
4066 56747550 : Word16 size = BINAURAL_CHANNELS * BINAURAL_CHANNELS;
4067 :
4068 56747550 : IF( Ascale == 1 )
4069 : {
4070 35332985 : min_q_shift = sub( s_min( L_norm_arr( Are_fx[0], size ), L_norm_arr( Aim_fx[0], size ) ), 1 );
4071 35332985 : scale_sig32( Are_fx[0], size, min_q_shift );
4072 35332985 : scale_sig32( Aim_fx[0], size, min_q_shift );
4073 35332985 : *q_A = add( *q_A, min_q_shift );
4074 35332985 : move16();
4075 : }
4076 :
4077 56747550 : IF( Bscale == 1 )
4078 : {
4079 0 : min_q_shift = sub( s_min( L_norm_arr( Bre_fx[0], size ), L_norm_arr( Bim_fx[0], size ) ), 1 );
4080 0 : scale_sig32( Bre_fx[0], size, min_q_shift );
4081 0 : scale_sig32( Bim_fx[0], size, min_q_shift );
4082 0 : *q_B = add( *q_B, min_q_shift );
4083 0 : move16();
4084 : }
4085 :
4086 170242650 : FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
4087 : {
4088 340485300 : FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
4089 : {
4090 : #ifdef IVAS_ENH64_CADENCE_CHANGES
4091 : outRe_fx[chA][chB] = W_extract_h( W_mac_32_32( W_mult_32_32( Are_fx[chA][0], Bre_fx[chB][0] ), Are_fx[chA][1], Bre_fx[chB][1] ) );
4092 : move32();
4093 : outRe_fx[chA][chB] = L_sub( outRe_fx[chA][chB], W_extract_h( W_mac_32_32( W_mult_32_32( Aim_fx[chA][0], L_negate( Bim_fx[chB][0] ) ), Aim_fx[chA][1], L_negate( Bim_fx[chB][1] ) ) ) );
4094 : move32();
4095 : outIm_fx[chA][chB] = W_extract_h( W_mac_32_32( W_mult_32_32( Aim_fx[chA][0], Bre_fx[chB][0] ), Aim_fx[chA][1], Bre_fx[chB][1] ) );
4096 : move32();
4097 : outIm_fx[chA][chB] = L_add( outIm_fx[chA][chB], W_extract_h( W_mac_32_32( W_mult_32_32( Are_fx[chA][0], L_negate( Bim_fx[chB][0] ) ), Are_fx[chA][1], L_negate( Bim_fx[chB][1] ) ) ) );
4098 : move32();
4099 : #else
4100 226990200 : outRe_fx[chA][chB] = Madd_32_32( Madd_32_32( Madd_32_32( Mpy_32_32( Are_fx[chA][0], Bre_fx[chB][0] ),
4101 226990200 : Are_fx[chA][1], Bre_fx[chB][1] ),
4102 226990200 : Aim_fx[chA][0], Bim_fx[chB][0] ),
4103 226990200 : Aim_fx[chA][1], Bim_fx[chB][1] );
4104 226990200 : move32();
4105 226990200 : outIm_fx[chA][chB] = Msub_32_32( Msub_32_32( Madd_32_32( Mpy_32_32( Aim_fx[chA][0], Bre_fx[chB][0] ),
4106 226990200 : Aim_fx[chA][1], Bre_fx[chB][1] ),
4107 226990200 : Are_fx[chA][0], Bim_fx[chB][0] ),
4108 226990200 : Are_fx[chA][1], Bim_fx[chB][1] );
4109 226990200 : move32();
4110 : #endif /* #ifdef IVAS_ENH64_CADENCE_CHANGES */
4111 : }
4112 : }
4113 56747550 : *q_out = sub( add( *q_A, *q_B ), 31 );
4114 56747550 : move16();
4115 :
4116 56747550 : if ( L_and( is_zero_arr( outRe_fx[0], size ), is_zero_arr( outIm_fx[0], size ) ) )
4117 : {
4118 207374 : *q_out = Q31;
4119 207374 : move16();
4120 : }
4121 56747550 : return;
4122 : }
4123 :
4124 :
4125 21414565 : static void chol2x2_fx(
4126 : const Word32 E1, /*q_E*/
4127 : const Word32 E2, /*q_E*/
4128 : Word16 q_E,
4129 : const Word32 Cre, /*q_C*/
4130 : const Word32 Cim, /*q_C*/
4131 : Word16 q_C,
4132 : Word32 outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_out*/
4133 : Word32 outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_out*/
4134 : Word16 *q_out )
4135 : {
4136 : Word16 chA, chB;
4137 : Word32 sqrtVal_fx, temp;
4138 : Word16 exp, q_re1, q_re2, q_re3, q_im, q_tmp;
4139 : Word32 e1, e2, c_re, c_im;
4140 : Word16 q_e, q_c;
4141 :
4142 21414565 : exp = sub( get_min_scalefactor( E1, E2 ), 1 );
4143 21414565 : e1 = L_shl( E1, exp );
4144 21414565 : e2 = L_shl( E2, exp );
4145 21414565 : q_e = add( q_E, exp );
4146 :
4147 21414565 : exp = sub( get_min_scalefactor( Cre, Cim ), 1 );
4148 21414565 : c_re = L_shl( Cre, exp );
4149 21414565 : c_im = L_shl( Cim, exp );
4150 21414565 : q_c = add( q_C, exp );
4151 :
4152 :
4153 64243695 : FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
4154 : {
4155 128487390 : FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
4156 : {
4157 85658260 : outRe[chA][chB] = 0;
4158 85658260 : move32();
4159 85658260 : outIm[chA][chB] = 0;
4160 85658260 : move32();
4161 : }
4162 : }
4163 :
4164 21414565 : IF( GT_32( e1, e2 ) ) /* Perform Cholesky decomposition according to louder channel first */
4165 : {
4166 10763752 : exp = sub( 31, q_e );
4167 10763752 : outRe[0][0] = Sqrt32( e1, &exp );
4168 10763752 : move32();
4169 10763752 : q_re1 = sub( 31, exp );
4170 :
4171 : // 4611686 = 1e-12 in Q62
4172 10763752 : IF( outRe[0][0] == 0 )
4173 : {
4174 0 : outRe[1][0] = BASOP_Util_Divide3232_Scale_newton( c_re, 4611686, &exp );
4175 0 : move32();
4176 0 : q_re2 = add( sub( 31, exp ), sub( q_c, 62 ) );
4177 :
4178 0 : outIm[1][0] = BASOP_Util_Divide3232_Scale_newton( c_im, 4611686, &exp );
4179 0 : move32();
4180 0 : q_im = add( sub( 31, exp ), sub( q_c, 62 ) );
4181 : }
4182 : ELSE
4183 : {
4184 : Word32 denom;
4185 : Word16 den_exp;
4186 : Word32 my_outRe, my_outIm;
4187 :
4188 : /* Compute denom = 1.0 / outRe[0][0] */
4189 10763752 : denom = ISqrt32( outRe[0][0], &exp );
4190 10763752 : denom = Mpy_32_32( denom, denom );
4191 10763752 : den_exp = shl( exp, 1 );
4192 :
4193 : /* Normalise c_re, c_im */
4194 10763752 : exp = norm_l( c_re );
4195 10763752 : my_outRe = L_shl( c_re, exp );
4196 10763752 : q_re2 = add( q_c, exp );
4197 10763752 : exp = norm_l( c_im );
4198 10763752 : my_outIm = L_shl( c_im, exp );
4199 10763752 : q_im = add( q_c, exp );
4200 :
4201 : /* Multiply and store c_re*denom and c_im*denom */
4202 10763752 : outRe[1][0] = Mpy_32_32( denom, my_outRe );
4203 10763752 : move32();
4204 10763752 : q_re2 = sub( q_re2, den_exp );
4205 :
4206 10763752 : outIm[1][0] = Mpy_32_32( denom, my_outIm );
4207 10763752 : move32();
4208 10763752 : q_im = sub( q_im, den_exp );
4209 : }
4210 10763752 : if ( outRe[1][0] == 0 )
4211 : {
4212 658 : q_re2 = Q31;
4213 658 : move16();
4214 : }
4215 10763752 : if ( outIm[1][0] == 0 )
4216 : {
4217 7290235 : q_im = Q31;
4218 7290235 : move16();
4219 : }
4220 :
4221 10763752 : temp = Madd_32_32( Mpy_32_32( c_re, c_re ), c_im, c_im );
4222 10763752 : q_tmp = sub( add( q_c, q_c ), 31 );
4223 :
4224 : // 4611686 = Q62
4225 10763752 : IF( e1 == 0 )
4226 : {
4227 0 : Word16 norm = norm_l( temp );
4228 0 : temp = L_shl( temp, norm );
4229 0 : q_tmp = add( q_tmp, norm );
4230 0 : temp = Mpy_32_32( temp, ONE_DIV_EPSILON_MANT );
4231 0 : q_tmp = sub( q_tmp, ONE_DIV_EPSILON_EXP );
4232 : }
4233 : ELSE
4234 : {
4235 10763752 : temp = BASOP_Util_Divide3232_Scale_newton( temp, e1, &exp );
4236 10763752 : q_tmp = add( sub( 31, exp ), sub( q_tmp, q_e ) );
4237 : }
4238 10763752 : if ( temp == 0 )
4239 : {
4240 633 : q_tmp = Q31;
4241 633 : move16();
4242 : }
4243 :
4244 10763752 : IF( LT_16( q_e, q_tmp ) )
4245 : {
4246 9611120 : sqrtVal_fx = L_sub( e2, L_shr( temp, sub( q_tmp, q_e ) ) ); ////q_tmp
4247 9611120 : q_tmp = q_e;
4248 9611120 : move16();
4249 : }
4250 : ELSE
4251 : {
4252 1152632 : sqrtVal_fx = L_sub( L_shr( e2, sub( q_e, q_tmp ) ), temp ); // q_tmp
4253 : }
4254 :
4255 10763752 : exp = sub( 31, q_tmp );
4256 10763752 : outRe[1][1] = Sqrt32( L_max( 0, sqrtVal_fx ), &exp );
4257 10763752 : move32();
4258 10763752 : q_re3 = sub( 31, exp );
4259 :
4260 10763752 : *q_out = s_min( s_min( q_re1, q_re2 ), s_min( q_re3, q_im ) );
4261 10763752 : outRe[0][0] = L_shr( outRe[0][0], sub( q_re1, *q_out ) );
4262 10763752 : move32();
4263 10763752 : outRe[1][0] = L_shr( outRe[1][0], sub( q_re2, *q_out ) );
4264 10763752 : move32();
4265 10763752 : outIm[1][0] = L_shr( outIm[1][0], sub( q_im, *q_out ) );
4266 10763752 : move32();
4267 10763752 : outRe[1][1] = L_shr( outRe[1][1], sub( q_re3, *q_out ) );
4268 10763752 : move32();
4269 : }
4270 : ELSE
4271 : {
4272 10650813 : exp = sub( 31, q_e );
4273 10650813 : outRe[1][1] = Sqrt32( e2, &exp );
4274 10650813 : move32();
4275 10650813 : q_re1 = sub( 31, exp );
4276 :
4277 : // 4611686 = Q62
4278 10650813 : IF( outRe[1][1] == 0 )
4279 : {
4280 : // outRe[0][1] = BASOP_Util_Divide3232_Scale_newton( c_re, 4611686, &exp );
4281 79726 : Word32 tmp1 = 1953125005; /* 1/4611686 Q62 */
4282 79726 : exp = 9;
4283 :
4284 79726 : outRe[0][1] = Mpy_32_32( tmp1, c_re );
4285 79726 : move32();
4286 79726 : q_re2 = add( sub( 31, exp ), sub( q_c, 62 ) );
4287 :
4288 : // outIm[0][1] = BASOP_Util_Divide3232_Scale_newton( -c_im, 4611686, &exp );
4289 79726 : outIm[0][1] = Mpy_32_32( tmp1, -c_im );
4290 79726 : move32();
4291 79726 : q_im = add( sub( 31, exp ), sub( q_c, 62 ) );
4292 : }
4293 : ELSE
4294 : {
4295 : {
4296 : // outRe[0][1] = BASOP_Util_Divide3232_Scale_newton( c_re, outRe[1][1], &exp );
4297 10571087 : Word32 tmp1 = BASOP_Util_Divide3232_Scale_newton( 0x7FFFFFFF, outRe[1][1], &exp );
4298 10571087 : outRe[0][1] = Mpy_32_32( tmp1, c_re );
4299 10571087 : move32();
4300 10571087 : q_re2 = add( sub( 31, exp ), sub( q_c, q_re1 ) );
4301 :
4302 : // outIm[0][1] = BASOP_Util_Divide3232_Scale_newton( -c_im, outRe[1][1], &exp );
4303 10571087 : outIm[0][1] = Mpy_32_32( tmp1, -c_im );
4304 10571087 : move32();
4305 10571087 : q_im = add( sub( 31, exp ), sub( q_c, q_re1 ) );
4306 : }
4307 : }
4308 10650813 : if ( outRe[0][1] == 0 )
4309 : {
4310 87647 : q_re2 = Q31;
4311 87647 : move16();
4312 : }
4313 10650813 : if ( outIm[0][1] == 0 )
4314 : {
4315 8736027 : q_im = Q31;
4316 8736027 : move16();
4317 : }
4318 :
4319 10650813 : temp = Madd_32_32( Mpy_32_32( c_re, c_re ), c_im, c_im );
4320 10650813 : q_tmp = sub( add( q_c, q_c ), 31 );
4321 :
4322 : // 4611686 = 1e-12 in Q62
4323 10650813 : IF( e2 == 0 )
4324 : {
4325 79726 : temp = BASOP_Util_Divide3232_Scale_newton( temp, 4611686, &exp );
4326 79726 : q_tmp = add( sub( 31, exp ), sub( q_tmp, 62 ) );
4327 : }
4328 : ELSE
4329 : {
4330 10571087 : temp = BASOP_Util_Divide3232_Scale_newton( temp, e2, &exp );
4331 10571087 : q_tmp = add( sub( 31, exp ), sub( q_tmp, q_e ) );
4332 : }
4333 10650813 : if ( temp == 0 )
4334 : {
4335 87630 : q_tmp = Q31;
4336 87630 : move16();
4337 : }
4338 :
4339 10650813 : IF( LT_16( q_e, q_tmp ) )
4340 : {
4341 9683435 : sqrtVal_fx = L_sub( e1, L_shr( temp, sub( q_tmp, q_e ) ) ); ////q_tmp
4342 9683435 : q_tmp = q_e;
4343 9683435 : move16();
4344 : }
4345 : ELSE
4346 : {
4347 967378 : sqrtVal_fx = L_sub( L_shr( e1, sub( q_e, q_tmp ) ), temp ); ////q_tmp
4348 : }
4349 :
4350 10650813 : exp = sub( 31, q_tmp );
4351 10650813 : outRe[0][0] = Sqrt32( L_max( 0, sqrtVal_fx ), &exp );
4352 10650813 : move32();
4353 10650813 : q_re3 = sub( 31, exp );
4354 :
4355 10650813 : *q_out = s_min( s_min( q_re1, q_re2 ), s_min( q_re3, q_im ) );
4356 10650813 : move16();
4357 10650813 : outRe[1][1] = L_shr( outRe[1][1], sub( q_re1, *q_out ) );
4358 10650813 : move32();
4359 10650813 : outRe[0][1] = L_shr( outRe[0][1], sub( q_re2, *q_out ) );
4360 10650813 : move32();
4361 10650813 : outIm[0][1] = L_shr( outIm[0][1], sub( q_im, *q_out ) );
4362 10650813 : move32();
4363 10650813 : outRe[0][0] = L_shr( outRe[0][0], sub( q_re3, *q_out ) );
4364 10650813 : move32();
4365 : }
4366 :
4367 21414565 : return;
4368 : }
4369 21414565 : static void formulate2x2MixingMatrix_fx(
4370 : Word32 Ein1_fx, /*q_Ein*/
4371 : Word32 Ein2_fx, /*q_Ein*/
4372 : Word16 q_Ein,
4373 : Word32 CinRe_fx, /*q_Cin*/
4374 : Word32 CinIm_fx, /*q_Cin*/
4375 : Word16 q_Cin,
4376 : Word32 Eout1_fx, /*q_Eout*/
4377 : Word32 Eout2_fx, /*q_Eout*/
4378 : Word16 q_Eout,
4379 : Word32 CoutRe_fx, /*q_Cout*/
4380 : Word32 CoutIm_fx, /*q_Cout*/
4381 : Word16 q_Cout,
4382 : Word32 Q_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], // Q31
4383 : Word32 Mre_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_M*/
4384 : Word32 Mim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_M*/
4385 : Word16 *q_M,
4386 : const Word16 regularizationFactor_fx /*Q14*/ )
4387 : {
4388 : /*
4389 : This function implements a 2x2 solution for an optimized spatial audio rendering algorithm
4390 : Vilkamo, J., Bäckström, T. and Kuntz, A., 2013.
4391 : "Optimized covariance domain framework for time–frequency processing of spatial audio."
4392 : Journal of the Audio Engineering Society, 61(6), pp.403-411.
4393 :
4394 : The result of the formulas below are the same as those in the publication, however, some
4395 : derivation details differ for as simple as possible 2x2 formulattion
4396 : */
4397 : Word16 chA, chB;
4398 : Word32 maxEne_fx, tmp, maxEneDiv_fx;
4399 : Word16 q_maxEne, q_maxEneDiv, exp, exp1;
4400 : Word32 KyRe_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], KyIm_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
4401 : Word32 Uxre_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Uxim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
4402 : Word32 Sx_fx[BINAURAL_CHANNELS], Kxre_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Kxim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
4403 : Word32 tmpRe_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], tmpIm_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
4404 : Word32 Are_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Aim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
4405 : Word32 Ure_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Uim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
4406 : Word32 D_fx[BINAURAL_CHANNELS];
4407 : Word32 div_fx[BINAURAL_CHANNELS];
4408 : Word32 Ghat_fx[BINAURAL_CHANNELS];
4409 : Word32 GhatQ_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
4410 : Word32 Pre_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Pim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
4411 : Word16 q_ky, q_Sx, q_Ux, q_Kx, q_A, q_U, q_D, q_P;
4412 : Word32 E_in1, E_in2, E_out1, E_out2, Cout_re, Cout_im, Cin_re, Cin_im;
4413 : Word16 q_ein, q_eout, q_cin, q_cout, q_Ghat, q_GhatQ, q_temp, q_div, exp_temp;
4414 : Word32 temp;
4415 : Word16 q_Pre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], q_Pim[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
4416 : Word16 hdrm_re[BINAURAL_CHANNELS][BINAURAL_CHANNELS], hdrm_im[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
4417 21414565 : set16_fx( hdrm_re[0], 63, i_mult( BINAURAL_CHANNELS, BINAURAL_CHANNELS ) );
4418 21414565 : set16_fx( hdrm_im[0], 63, i_mult( BINAURAL_CHANNELS, BINAURAL_CHANNELS ) );
4419 21414565 : set16_fx( q_Pre[0], Q31, i_mult( BINAURAL_CHANNELS, BINAURAL_CHANNELS ) );
4420 21414565 : set16_fx( q_Pim[0], Q31, i_mult( BINAURAL_CHANNELS, BINAURAL_CHANNELS ) );
4421 :
4422 21414565 : q_ky = 0;
4423 21414565 : move16();
4424 21414565 : q_Sx = 0;
4425 21414565 : move16();
4426 21414565 : q_Ux = 0;
4427 21414565 : move16();
4428 21414565 : q_Kx = 0;
4429 21414565 : move16();
4430 :
4431 21414565 : exp = sub( get_min_scalefactor( Ein1_fx, Ein2_fx ), 1 );
4432 21414565 : E_in1 = L_shl( Ein1_fx, exp );
4433 21414565 : E_in2 = L_shl( Ein2_fx, exp );
4434 21414565 : q_ein = add( q_Ein, exp );
4435 :
4436 21414565 : exp = sub( get_min_scalefactor( Eout1_fx, Eout2_fx ), 1 );
4437 21414565 : E_out1 = L_shl( Eout1_fx, exp );
4438 21414565 : E_out2 = L_shl( Eout2_fx, exp );
4439 21414565 : q_eout = add( q_Eout, exp );
4440 :
4441 21414565 : exp = sub( get_min_scalefactor( CinRe_fx, CinIm_fx ), 1 );
4442 21414565 : Cin_re = L_shl( CinRe_fx, exp );
4443 21414565 : Cin_im = L_shl( CinIm_fx, exp );
4444 21414565 : q_cin = add( q_Cin, exp );
4445 :
4446 21414565 : exp = sub( get_min_scalefactor( CoutRe_fx, CoutIm_fx ), 1 );
4447 21414565 : Cout_re = L_shl( CoutRe_fx, exp );
4448 21414565 : Cout_im = L_shl( CoutIm_fx, exp );
4449 21414565 : q_cout = add( q_Cout, exp );
4450 :
4451 : /* Normalize energy values */
4452 21414565 : maxEne_fx = L_max( E_in1, E_in2 );
4453 21414565 : q_maxEne = q_ein;
4454 21414565 : move16();
4455 :
4456 21414565 : tmp = L_max( E_out1, E_out2 );
4457 21414565 : IF( LT_16( q_maxEne, q_eout ) )
4458 : {
4459 11290014 : maxEne_fx = L_max( maxEne_fx, L_shr( tmp, sub( q_eout, q_maxEne ) ) ); // q_maxEne
4460 : }
4461 : ELSE
4462 : {
4463 10124551 : maxEne_fx = L_max( L_shr( maxEne_fx, sub( q_maxEne, q_eout ) ), tmp ); // q_maxEne
4464 10124551 : q_maxEne = q_eout;
4465 10124551 : move16();
4466 : }
4467 :
4468 : // 4611686 = Q62
4469 21414565 : IF( maxEne_fx == 0 )
4470 : {
4471 48892 : maxEneDiv_fx = ONE_DIV_EPSILON_MANT;
4472 48892 : move32();
4473 48892 : q_maxEneDiv = 31 - ONE_DIV_EPSILON_EXP;
4474 48892 : move16();
4475 : }
4476 : ELSE
4477 : {
4478 21365673 : maxEneDiv_fx = BASOP_Util_Divide3232_Scale_newton( ONE_IN_Q30, maxEne_fx, &exp );
4479 21365673 : q_maxEneDiv = add( sub( 31, exp ), sub( Q30, q_maxEne ) );
4480 : }
4481 21414565 : exp = norm_l( maxEneDiv_fx );
4482 21414565 : maxEneDiv_fx = L_shl( maxEneDiv_fx, exp );
4483 21414565 : q_maxEneDiv = add( q_maxEneDiv, exp );
4484 :
4485 21414565 : E_in1 = Mpy_32_32( E_in1, maxEneDiv_fx );
4486 21414565 : E_in2 = Mpy_32_32( E_in2, maxEneDiv_fx );
4487 21414565 : q_ein = sub( add( q_ein, q_maxEneDiv ), 31 );
4488 :
4489 21414565 : Cin_re = Mpy_32_32( Cin_re, maxEneDiv_fx );
4490 21414565 : Cin_im = Mpy_32_32( Cin_im, maxEneDiv_fx );
4491 21414565 : q_cin = sub( add( q_cin, q_maxEneDiv ), 31 );
4492 :
4493 21414565 : E_out1 = Mpy_32_32( E_out1, maxEneDiv_fx );
4494 21414565 : E_out2 = Mpy_32_32( E_out2, maxEneDiv_fx );
4495 21414565 : q_eout = sub( add( q_eout, q_maxEneDiv ), 31 );
4496 :
4497 21414565 : Cout_re = Mpy_32_32( Cout_re, maxEneDiv_fx );
4498 21414565 : Cout_im = Mpy_32_32( Cout_im, maxEneDiv_fx );
4499 21414565 : q_cout = sub( add( q_cout, q_maxEneDiv ), 31 );
4500 :
4501 : /* Cholesky decomposition of target / output covariance matrix */
4502 21414565 : chol2x2_fx( E_out1, E_out2, q_eout, Cout_re, Cout_im, q_cout, KyRe_fx, KyIm_fx, &q_ky );
4503 :
4504 : /* Eigendecomposition of input covariance matrix */
4505 21414565 : eig2x2_fx( E_in1, E_in2, q_ein, Cin_re, Cin_im, q_cin, Uxre_fx, Uxim_fx, &q_Ux, Sx_fx, &q_Sx );
4506 :
4507 : /* Eigendecomposition to Kx -- Ux Sx Ux' -> Kx Kx'*/
4508 21414565 : exp = sub( 31, q_Sx );
4509 21414565 : exp1 = sub( 31, q_Sx );
4510 21414565 : Sx_fx[0] = Sqrt32( Sx_fx[0], &exp );
4511 21414565 : move32();
4512 21414565 : Sx_fx[1] = Sqrt32( Sx_fx[1], &exp1 );
4513 21414565 : move32();
4514 21414565 : q_Sx = sub( 31, s_max( exp, exp1 ) );
4515 21414565 : Word16 q_diff = sub( 31, q_Sx );
4516 21414565 : Sx_fx[0] = L_shr( Sx_fx[0], sub( q_diff, exp ) ); // q_Sx
4517 21414565 : move32();
4518 21414565 : Sx_fx[1] = L_shr( Sx_fx[1], sub( q_diff, exp1 ) ); // q_Sx
4519 21414565 : move32();
4520 :
4521 21414565 : matrixDiagMul_fx( Uxre_fx, Uxim_fx, q_Ux, Sx_fx, q_Sx, Kxre_fx, Kxim_fx, &q_Kx );
4522 :
4523 : /* Regularize the diagonal Sx for matrix inversion */
4524 21414565 : Sx_fx[0] = L_max( L_shr( Sx_fx[0], 1 ), Mpy_32_16_1( Sx_fx[1], regularizationFactor_fx ) );
4525 21414565 : Sx_fx[1] = L_max( L_shr( Sx_fx[1], 1 ), L_shl( Mpy_32_16_1( Sx_fx[0], regularizationFactor_fx ), 1 ) );
4526 21414565 : move32();
4527 21414565 : move32();
4528 21414565 : q_Sx = sub( add( q_Sx, Q14 ), 15 );
4529 :
4530 21414565 : temp = Mpy_32_32( E_in2, 2147484 ); // 2147484 = 0.001f in Q31
4531 21414565 : temp = L_max( temp, E_in1 );
4532 :
4533 21414565 : IF( temp == 0 )
4534 : {
4535 48892 : IF( E_out1 == 0 )
4536 : {
4537 48892 : Ghat_fx[0] = 0;
4538 48892 : exp = -19;
4539 48892 : move32();
4540 48892 : move16();
4541 : }
4542 : ELSE
4543 : {
4544 0 : temp = BASOP_Util_Divide3232_Scale_newton( E_out1, 4611686, &exp ); // 4611686 = Q62
4545 0 : exp = sub( exp, sub( q_eout, 62 ) );
4546 0 : Ghat_fx[0] = Sqrt32( temp, &exp ); // Q = 31 - exp
4547 : }
4548 : }
4549 : ELSE
4550 : {
4551 21365673 : temp = BASOP_Util_Add_Mant32Exp( temp, sub( 31, q_ein ), EPSILON_MANT, EPSILON_EXP, &exp_temp );
4552 :
4553 21365673 : temp = BASOP_Util_Divide3232_Scale_newton( E_out1, temp, &exp );
4554 21365673 : exp = sub( exp, sub( q_eout, sub( 31, exp_temp ) ) );
4555 21365673 : Ghat_fx[0] = Sqrt32( temp, &exp ); // Q = 31 - exp
4556 : }
4557 21414565 : move32();
4558 :
4559 21414565 : temp = Mpy_32_32( E_in1, 2147484 ); // 2147484 = 0.001f in Q31
4560 21414565 : temp = L_max( temp, E_in2 ); // q_ein
4561 21414565 : IF( temp == 0 )
4562 : {
4563 48892 : IF( E_out2 == 0 )
4564 : { /* We can set hard-coded results */
4565 48892 : Ghat_fx[1] = 0;
4566 48892 : exp1 = -19;
4567 48892 : move16();
4568 : }
4569 : ELSE
4570 : {
4571 0 : temp = BASOP_Util_Divide3232_Scale_newton( E_out2, 4611686, &exp1 ); // 4611686 = Q62
4572 0 : exp1 = sub( exp1, sub( q_eout, 62 ) );
4573 0 : Ghat_fx[1] = Sqrt32( temp, &exp1 ); // Q = 31 - exp1
4574 : }
4575 : }
4576 : ELSE
4577 : {
4578 21365673 : temp = BASOP_Util_Add_Mant32Exp( temp, sub( 31, q_ein ), EPSILON_MANT, EPSILON_EXP, &exp_temp );
4579 :
4580 21365673 : temp = BASOP_Util_Divide3232_Scale_newton( E_out2, temp, &exp1 );
4581 21365673 : exp1 = sub( exp1, sub( q_eout, sub( 31, exp_temp ) ) );
4582 21365673 : Ghat_fx[1] = Sqrt32( temp, &exp1 ); // Q = 31 - exp1
4583 : }
4584 21414565 : move32();
4585 :
4586 21414565 : q_Ghat = sub( 31, s_max( exp, exp1 ) );
4587 21414565 : q_diff = sub( 31, q_Ghat );
4588 21414565 : Ghat_fx[0] = L_shr( Ghat_fx[0], sub( q_diff, exp ) ); // q_Ghat
4589 21414565 : move32();
4590 21414565 : Ghat_fx[1] = L_shr( Ghat_fx[1], sub( q_diff, exp1 ) ); // q_Ghat
4591 21414565 : move32();
4592 :
4593 : /* Matrix multiplication, tmp = Ky' * G_hat * Q */
4594 64243695 : FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
4595 : {
4596 42829130 : GhatQ_fx[chA][0] = Mpy_32_32( Q_fx[chA][0], Ghat_fx[chA] );
4597 42829130 : GhatQ_fx[chA][1] = Mpy_32_32( Q_fx[chA][1], Ghat_fx[chA] );
4598 42829130 : move32();
4599 42829130 : move32();
4600 : }
4601 21414565 : q_GhatQ = sub( add( Q31, q_Ghat ), 31 );
4602 :
4603 21414565 : exp = sub( s_min( L_norm_arr( KyRe_fx[0], i_mult( BINAURAL_CHANNELS, BINAURAL_CHANNELS ) ), L_norm_arr( KyIm_fx[0], i_mult( BINAURAL_CHANNELS, BINAURAL_CHANNELS ) ) ), 1 );
4604 21414565 : scale_sig32( KyRe_fx[0], BINAURAL_CHANNELS * BINAURAL_CHANNELS, exp );
4605 21414565 : scale_sig32( KyIm_fx[0], BINAURAL_CHANNELS * BINAURAL_CHANNELS, exp );
4606 21414565 : q_ky = add( q_ky, exp );
4607 :
4608 64243695 : FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
4609 : {
4610 128487390 : FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
4611 : {
4612 85658260 : tmpRe_fx[chA][chB] = Madd_32_32( Mpy_32_32( KyRe_fx[0][chA], GhatQ_fx[0][chB] ), KyRe_fx[1][chA], GhatQ_fx[1][chB] );
4613 85658260 : tmpIm_fx[chA][chB] = Msub_32_32( Mpy_32_32( L_negate( KyIm_fx[0][chA] ), GhatQ_fx[0][chB] ), KyIm_fx[1][chA], GhatQ_fx[1][chB] );
4614 85658260 : move32();
4615 85658260 : move32();
4616 : }
4617 : }
4618 :
4619 21414565 : q_temp = sub( add( q_ky, q_GhatQ ), 31 );
4620 :
4621 : /* A = Ky' * G_hat * Q * Kx (see publication) */
4622 21414565 : matrixMul_fx( tmpRe_fx, tmpIm_fx, &q_temp, Kxre_fx, Kxim_fx, &q_Kx, Are_fx, Aim_fx, &q_A );
4623 :
4624 : /* Find nearest orthonormal matrix P to A = Ky' * G_hat * Q * Kx
4625 : For matrix A that is P = A(A'A)^0.5 */
4626 21414565 : matrixTransp1Mul_fx( Are_fx, Aim_fx, q_A, Are_fx, Aim_fx, q_A, tmpRe_fx, tmpIm_fx, &q_temp );
4627 :
4628 21414565 : eig2x2_fx( tmpRe_fx[0][0], tmpRe_fx[1][1], q_temp, tmpRe_fx[1][0], tmpIm_fx[1][0], q_temp, Ure_fx, Uim_fx, &q_U, D_fx, &q_D );
4629 :
4630 21414565 : IF( D_fx[0] == 0 )
4631 : {
4632 167991 : temp = ONE_DIV_EPSILON_MANT; /* Result of 1.0/eps with full precision */
4633 167991 : move32();
4634 167991 : exp = ONE_DIV_EPSILON_EXP;
4635 167991 : move16();
4636 : }
4637 : ELSE
4638 : {
4639 21246574 : temp = BASOP_Util_Divide3232_Scale_newton( ONE_IN_Q30, D_fx[0], &exp );
4640 21246574 : exp = sub( exp, sub( Q30, q_D ) );
4641 : }
4642 21414565 : div_fx[0] = Sqrt32( temp, &exp ); // Q = 31 - exp
4643 21414565 : move32();
4644 :
4645 : // Sqrt(1)
4646 21414565 : div_fx[1] = L_add( 0, 2047986068 ); // Q = 31 - exp1
4647 21414565 : exp1 = add( 0, 20 );
4648 :
4649 21414565 : IF( D_fx[1] != 0 ) // This is the new code: replace div sqrt by isqrt
4650 : {
4651 16760377 : exp1 = sub( 31, q_D );
4652 16760377 : div_fx[1] = ISqrt32( D_fx[1], &exp1 );
4653 16760377 : move32();
4654 : }
4655 21414565 : q_div = sub( 31, s_max( exp, exp1 ) );
4656 :
4657 21414565 : div_fx[0] = L_shr( div_fx[0], sub( sub( 31, exp ), q_div ) ); // q_div
4658 21414565 : move32();
4659 21414565 : div_fx[1] = L_shr( div_fx[1], sub( sub( 31, exp1 ), q_div ) ); // q_div
4660 21414565 : move32();
4661 :
4662 : // 1310720000 = 10,000.0f in Q17
4663 21414565 : Word32 thresh = L_shl_sat( 1310720000, sub( q_div, Q17 ) ); // q_div
4664 21414565 : div_fx[0] = L_min( div_fx[0], thresh ); // q_div
4665 21414565 : div_fx[1] = L_min( div_fx[1], thresh ); // q_div
4666 :
4667 21414565 : matrixMul_fx( Are_fx, Aim_fx, &q_A, Ure_fx, Uim_fx, &q_U, tmpRe_fx, tmpIm_fx, &q_temp );
4668 :
4669 21414565 : exp = L_norm_arr( div_fx, BINAURAL_CHANNELS );
4670 21414565 : scale_sig32( div_fx, BINAURAL_CHANNELS, exp );
4671 21414565 : q_div = add( q_div, exp );
4672 :
4673 64243695 : FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
4674 : {
4675 128487390 : FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
4676 : {
4677 : Word64 W_tmp;
4678 :
4679 85658260 : W_tmp = W_mult0_32_32( tmpRe_fx[chA][chB], div_fx[chB] );
4680 85658260 : IF( W_tmp != 0 )
4681 : {
4682 75353238 : Word16 hdrm = sub( W_norm( W_tmp ), 32 );
4683 75353238 : tmpRe_fx[chA][chB] = W_shl_sat_l( W_tmp, hdrm );
4684 75353238 : move32();
4685 75353238 : hdrm_re[chA][chB] = add( add( q_temp, q_div ), hdrm );
4686 75353238 : move16();
4687 : }
4688 : ELSE
4689 : {
4690 10305022 : tmpRe_fx[chA][chB] = 0;
4691 10305022 : move32();
4692 : }
4693 :
4694 85658260 : W_tmp = W_mult0_32_32( tmpIm_fx[chA][chB], div_fx[chB] );
4695 85658260 : IF( W_tmp != 0 )
4696 : {
4697 53692700 : Word16 hdrm = sub( W_norm( W_tmp ), 32 );
4698 53692700 : move16();
4699 53692700 : tmpIm_fx[chA][chB] = W_shl_sat_l( W_tmp, hdrm );
4700 53692700 : move32();
4701 53692700 : hdrm_im[chA][chB] = add( add( q_temp, q_div ), hdrm );
4702 53692700 : move16();
4703 : }
4704 : ELSE
4705 : {
4706 31965560 : tmpIm_fx[chA][chB] = 0;
4707 31965560 : move32();
4708 : }
4709 : }
4710 : }
4711 :
4712 21414565 : minimum_s( hdrm_re[0], i_mult( BINAURAL_CHANNELS, BINAURAL_CHANNELS ), &exp );
4713 21414565 : q_temp = exp;
4714 21414565 : move16();
4715 21414565 : minimum_s( hdrm_im[0], BINAURAL_CHANNELS * BINAURAL_CHANNELS, &exp );
4716 21414565 : q_temp = s_min( q_temp, exp );
4717 21414565 : q_temp = sub( q_temp, 1 );
4718 :
4719 64243695 : FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
4720 : {
4721 128487390 : FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
4722 : {
4723 85658260 : tmpRe_fx[chA][chB] = L_shr( tmpRe_fx[chA][chB], sub( hdrm_re[chA][chB], q_temp ) );
4724 85658260 : tmpIm_fx[chA][chB] = L_shr( tmpIm_fx[chA][chB], sub( hdrm_im[chA][chB], q_temp ) );
4725 85658260 : move32();
4726 85658260 : move32();
4727 : }
4728 : }
4729 :
4730 21414565 : matrixTransp2Mul_fx( tmpRe_fx, tmpIm_fx, &q_temp, Ure_fx, Uim_fx, &q_U,
4731 : 0 /*int Ascale*/,
4732 : 0 /*int Bscale*/,
4733 : Pre_fx, Pim_fx, &q_P ); /* Nearest orthonormal matrix P to matrix A formulated */
4734 :
4735 : /* These are the final formulas of the JAES publication M = Ky P Kx^(-1) */
4736 : #if ( BINAURAL_CHANNELS != 2 )
4737 : FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
4738 : {
4739 : FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
4740 : {
4741 : IF( Sx_fx[chB] == 0 )
4742 : {
4743 : Pre_fx[chA][chB] = Mpy_32_32( Pre_fx[chA][chB], ONE_DIV_EPSILON_MANT );
4744 : // q_Pre[chA][chB] = add(sub(31, q_P), 31 - ONE_DIV_EPSILON_EXP);
4745 : q_Pre[chA][chB] = sub( 62 - ONE_DIV_EPSILON_EXP, q_P );
4746 :
4747 :
4748 : Pim_fx[chA][chB] = Mpy_32_32( Pim_fx[chA][chB], ONE_DIV_EPSILON_MANT );
4749 : // q_Pim[chA][chB] = add(sub(31, q_P), 31 - ONE_DIV_EPSILON_EXP);
4750 : q_Pim[chA][chB] = sub( 62 - ONE_DIV_EPSILON_EXP, q_P );
4751 : }
4752 : ELSE
4753 : {
4754 : Word16 Pre_shift, Pim_shift;
4755 : temp = BASOP_Util_Add_Mant32Exp( Sx_fx[chB], sub( 31, q_Sx ), EPSILON_MANT, EPSILON_EXP, &exp_temp );
4756 :
4757 : temp = BASOP_Util_Divide3232_Scale_newton( ONE_IN_Q30, temp, &exp );
4758 : Pre_shift = norm_l( Pre_fx[chA][chB] );
4759 : Pim_shift = norm_l( Pim_fx[chA][chB] );
4760 : Pre_fx[chA][chB] = Mpy_32_32( L_shl( Pre_fx[chA][chB], Pre_shift ), temp );
4761 : Pim_fx[chA][chB] = Mpy_32_32( L_shl( Pim_fx[chA][chB], Pim_shift ), temp );
4762 : q_temp = add( sub( sub( q_P, exp ), sub( 31, Q30 ) ), exp_temp );
4763 : q_Pre[chA][chB] = add( q_temp, Pre_shift );
4764 : q_Pim[chA][chB] = add( q_temp, Pim_shift );
4765 : }
4766 : if ( Pre_fx[chA][chB] == 0 )
4767 : {
4768 : q_Pre[chA][chB] = 31;
4769 : move16();
4770 : }
4771 : if ( Pim_fx[chA][chB] == 0 )
4772 : {
4773 : q_Pim[chA][chB] = 31;
4774 : move16();
4775 : }
4776 : move32();
4777 : move32();
4778 : move16();
4779 : move16();
4780 : }
4781 : }
4782 : #else
4783 : /* BINAURAL_CHANNEL == 2 */
4784 64243695 : FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
4785 : {
4786 42829130 : IF( Sx_fx[chB] == 0 )
4787 : {
4788 97784 : Pre_fx[0][chB] = Mpy_32_32( Pre_fx[0][chB], ONE_DIV_EPSILON_MANT );
4789 97784 : q_Pre[0][chB] = sub( 62 - ONE_DIV_EPSILON_EXP, q_P );
4790 97784 : Pim_fx[0][chB] = Mpy_32_32( Pim_fx[0][chB], ONE_DIV_EPSILON_MANT );
4791 97784 : q_Pim[0][chB] = sub( 62 - ONE_DIV_EPSILON_EXP, q_P );
4792 97784 : Pre_fx[1][chB] = Mpy_32_32( Pre_fx[1][chB], ONE_DIV_EPSILON_MANT );
4793 97784 : q_Pre[1][chB] = sub( 62 - ONE_DIV_EPSILON_EXP, q_P );
4794 97784 : Pim_fx[1][chB] = Mpy_32_32( Pim_fx[1][chB], ONE_DIV_EPSILON_MANT );
4795 97784 : q_Pim[1][chB] = sub( 62 - ONE_DIV_EPSILON_EXP, q_P );
4796 : }
4797 : ELSE
4798 : {
4799 : Word16 Pre_shift, Pim_shift;
4800 42731346 : temp = BASOP_Util_Add_Mant32Exp( Sx_fx[chB], sub( 31, q_Sx ), EPSILON_MANT, EPSILON_EXP, &exp_temp );
4801 42731346 : temp = BASOP_Util_Divide3232_Scale_newton( ONE_IN_Q30, temp, &exp );
4802 42731346 : q_temp = add( sub( sub( q_P, exp ), sub( 31, Q30 ) ), exp_temp );
4803 :
4804 42731346 : Pre_shift = norm_l( Pre_fx[0][chB] );
4805 42731346 : Pim_shift = norm_l( Pim_fx[0][chB] );
4806 42731346 : Pre_fx[0][chB] = Mpy_32_32( L_shl( Pre_fx[0][chB], Pre_shift ), temp );
4807 42731346 : Pim_fx[0][chB] = Mpy_32_32( L_shl( Pim_fx[0][chB], Pim_shift ), temp );
4808 42731346 : q_Pre[0][chB] = add( q_temp, Pre_shift );
4809 42731346 : q_Pim[0][chB] = add( q_temp, Pim_shift );
4810 :
4811 42731346 : Pre_shift = norm_l( Pre_fx[1][chB] );
4812 42731346 : Pim_shift = norm_l( Pim_fx[1][chB] );
4813 42731346 : Pre_fx[1][chB] = Mpy_32_32( L_shl( Pre_fx[1][chB], Pre_shift ), temp );
4814 42731346 : Pim_fx[1][chB] = Mpy_32_32( L_shl( Pim_fx[1][chB], Pim_shift ), temp );
4815 42731346 : q_Pre[1][chB] = add( q_temp, Pre_shift );
4816 42731346 : q_Pim[1][chB] = add( q_temp, Pim_shift );
4817 : }
4818 42829130 : if ( Pre_fx[0][chB] == 0 )
4819 : {
4820 4721698 : q_Pre[0][chB] = 31;
4821 4721698 : move16();
4822 : }
4823 42829130 : if ( Pim_fx[0][chB] == 0 )
4824 : {
4825 15586382 : q_Pim[0][chB] = 31;
4826 15586382 : move16();
4827 : }
4828 42829130 : if ( Pre_fx[1][chB] == 0 )
4829 : {
4830 5575535 : q_Pre[1][chB] = 31;
4831 5575535 : move16();
4832 : }
4833 42829130 : if ( Pim_fx[1][chB] == 0 )
4834 : {
4835 16288420 : q_Pim[1][chB] = 31;
4836 16288420 : move16();
4837 : }
4838 42829130 : move32();
4839 42829130 : move32();
4840 42829130 : move16();
4841 42829130 : move16();
4842 42829130 : move32();
4843 42829130 : move32();
4844 42829130 : move16();
4845 42829130 : move16();
4846 : }
4847 : #endif
4848 21414565 : minimum_s( q_Pre[0], BINAURAL_CHANNELS * BINAURAL_CHANNELS, &exp );
4849 21414565 : q_P = s_min( q_P, exp );
4850 21414565 : minimum_s( q_Pim[0], BINAURAL_CHANNELS * BINAURAL_CHANNELS, &exp );
4851 21414565 : q_P = s_min( q_P, exp );
4852 :
4853 64243695 : FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
4854 : {
4855 128487390 : FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
4856 : {
4857 85658260 : Pre_fx[chA][chB] = L_shr( Pre_fx[chA][chB], sub( q_Pre[chA][chB], q_P ) ); // q_P
4858 85658260 : Pim_fx[chA][chB] = L_shr( Pim_fx[chA][chB], sub( q_Pim[chA][chB], q_P ) ); // q_P
4859 85658260 : move32();
4860 85658260 : move32();
4861 : }
4862 : }
4863 :
4864 21414565 : matrixMul_fx( KyRe_fx, KyIm_fx, &q_ky, Pre_fx, Pim_fx, &q_P, tmpRe_fx, tmpIm_fx, &q_temp );
4865 :
4866 21414565 : matrixTransp2Mul_fx( tmpRe_fx, tmpIm_fx, &q_temp, Uxre_fx, Uxim_fx, &q_Ux,
4867 : 1 /*int Ascale*/,
4868 : 0 /*int Bscale*/,
4869 : Mre_fx, Mim_fx, q_M );
4870 21414565 : return;
4871 : }
4872 :
4873 :
4874 20805489 : static void getDirectPartGains_fx(
4875 : const Word16 bin,
4876 : Word16 aziDeg,
4877 : Word16 eleDeg,
4878 : Word32 *lRealp,
4879 : Word32 *lImagp,
4880 : Word32 *rRealp,
4881 : Word32 *rImagp,
4882 : const UWord8 renderStereoOutputInsteadOfBinaural,
4883 : Word32 Rmat[3][3], /*Q30*/
4884 : PARAMBIN_HRTF_GAIN_CACHE *gainCache,
4885 : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
4886 : const Word16 isHeadtracked,
4887 : HRTFS_PARAMBIN_HANDLE hHrtfParambin
4888 : #else
4889 : const Word16 isHeadtracked
4890 : #endif
4891 : )
4892 : {
4893 : // float aziRad, eleRad;
4894 : Word32 y, mappedX;
4895 : Word16 aziRadMapped, A, A2, A3;
4896 20805489 : const Word16 LsAngleRad = 17157; // Q15
4897 20805489 : move16();
4898 : Word32 *ptr_sin, *ptr_cos;
4899 : Word32 sin_val, cos_val;
4900 : Word16 e_mappedX;
4901 :
4902 20805489 : ptr_sin = &sine_table_Q31[180]; // sin[x] = sine_table_Q31[180 + x]
4903 20805489 : ptr_cos = cosine_table_Q31;
4904 :
4905 20805489 : IF( renderStereoOutputInsteadOfBinaural ) /* In stereo (i.e. non-binaural) rendering mode */
4906 : {
4907 : /* Convert azi and ele to an azi value of the cone of confusion */
4908 :
4909 : // y = ( sinf( aziRad ) * cosf( eleRad ) );
4910 :
4911 1589746 : IF( GT_16( abs_s( eleDeg ), 180 ) )
4912 : {
4913 : // cos(180 + x) = -cos(x)
4914 0 : cos_val = -ptr_cos[sub( abs_s( eleDeg ), 180 )]; // Q31
4915 : }
4916 : ELSE
4917 : {
4918 1589746 : cos_val = ptr_cos[abs_s( eleDeg )]; // Q31
4919 : }
4920 1589746 : move32();
4921 :
4922 1589746 : IF( GT_16( aziDeg, 180 ) )
4923 : {
4924 : // sin(180 + x) = -sin(x)
4925 0 : sin_val = -ptr_sin[sub( aziDeg, 180 )]; // Q31
4926 : }
4927 1589746 : ELSE IF( LT_16( aziDeg, -180 ) )
4928 : {
4929 : // sin(-(180 + x)) = sin(180 + x) = sinx
4930 0 : sin_val = ptr_sin[sub( abs_s( aziDeg ), 180 )]; // Q31
4931 : }
4932 : ELSE
4933 : {
4934 1589746 : sin_val = ptr_sin[aziDeg]; // Q31
4935 : }
4936 1589746 : move32();
4937 :
4938 1589746 : y = Mpy_32_32( sin_val, cos_val ); // Q31
4939 1589746 : e_mappedX = 0;
4940 1589746 : move16();
4941 1589746 : mappedX = Sqrt32( L_max( 0, L_sub( ONE_IN_Q31, Mpy_32_32( y, y ) ) ), &e_mappedX );
4942 :
4943 1589746 : aziRadMapped = BASOP_util_atan2( y, mappedX, negate( e_mappedX ) ); // Q13
4944 :
4945 : /* Determine the real valued amplitude panning gains */
4946 1589746 : *lImagp = 0;
4947 1589746 : *rImagp = 0;
4948 1589746 : move32();
4949 1589746 : move32();
4950 1589746 : IF( GE_16( aziRadMapped, shr( LsAngleRad, 2 ) ) )
4951 : { /* Left side */
4952 361666 : *lRealp = ONE_IN_Q31;
4953 361666 : *rRealp = 0;
4954 361666 : move32();
4955 361666 : move32();
4956 : }
4957 1228080 : ELSE IF( LE_16( aziRadMapped, negate( shr( LsAngleRad, 2 ) ) ) )
4958 : { /* Right side */
4959 569969 : *lRealp = 0;
4960 569969 : *rRealp = ONE_IN_Q31;
4961 569969 : move32();
4962 569969 : move32();
4963 : }
4964 : ELSE /* Tangent panning law */
4965 : {
4966 : Word16 e_div, div, e_a, e_a3, temp_16_1, temp_16_2, e_num, e_den;
4967 658111 : div = BASOP_Util_Divide3232_Scale( y, mappedX, &e_div );
4968 658111 : e_div = sub( e_div, e_mappedX );
4969 :
4970 658111 : A = mult( div, INV_TAN30_FX );
4971 658111 : e_a = add( e_div, 1 );
4972 :
4973 658111 : e_num = BASOP_Util_Add_MantExp( A, e_a, -32767, 0, &temp_16_1 );
4974 658111 : e_den = BASOP_Util_Add_MantExp( A, e_a, 32767, 0, &temp_16_2 );
4975 658111 : IF( temp_16_2 <= 0 )
4976 : {
4977 0 : temp_16_2 = 32;
4978 0 : e_den = 0;
4979 0 : move16();
4980 0 : move16();
4981 : }
4982 658111 : A2 = BASOP_Util_Divide1616_Scale( temp_16_1, temp_16_2, &e_div );
4983 658111 : e_div = add( e_div, sub( e_num, e_den ) );
4984 :
4985 658111 : e_den = BASOP_Util_Add_MantExp( mult( A2, A2 ), add( e_div, e_div ), 32767, 0, &temp_16_2 );
4986 658111 : A3 = BASOP_Util_Divide1616_Scale( 32767, temp_16_2, &e_a3 );
4987 658111 : e_a3 = sub( e_a3, e_den );
4988 : // A3 = 1.0f / ( A2 * A2 + 1.0f ); // Q15
4989 658111 : Word32 temp_32 = L_shr( L_deposit_h( A3 ), sub( 0, e_a3 ) );
4990 658111 : Word16 temp_e = 0;
4991 658111 : e_a3 = 0;
4992 658111 : move16();
4993 658111 : move16();
4994 658111 : *lRealp = Sqrt32( temp_32, &e_a3 );
4995 658111 : *rRealp = Sqrt32( L_sub( ONE_IN_Q31, temp_32 ), &temp_e );
4996 658111 : *lRealp = L_shr( *lRealp, sub( 0, e_a3 ) ); // Q31
4997 658111 : *rRealp = L_shr( *rRealp, sub( 0, temp_e ) ); // Q31
4998 658111 : move32();
4999 658111 : move32();
5000 658111 : move32();
5001 658111 : move32();
5002 : }
5003 :
5004 : /* Scaling to have the same expected gain as for the HRTF rendering */
5005 1589746 : *lRealp = Mpy_32_32( *lRealp, SQRT2_FIXED ); // Q30
5006 1589746 : *rRealp = Mpy_32_32( *rRealp, SQRT2_FIXED ); // Q30
5007 :
5008 1589746 : *lRealp = L_shr( *lRealp, 2 ); // Q28
5009 1589746 : *rRealp = L_shr( *rRealp, 2 ); // Q28
5010 1589746 : move32();
5011 1589746 : move32();
5012 1589746 : move32();
5013 1589746 : move32();
5014 : }
5015 : ELSE /* In regular binaural rendering mode */
5016 : {
5017 19215743 : test();
5018 19215743 : IF( EQ_16( aziDeg, gainCache->azi ) && EQ_16( eleDeg, gainCache->ele ) )
5019 : {
5020 : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
5021 11830041 : hrtfShGetHrtf_fx( bin, aziDeg, eleDeg, lRealp, lImagp, rRealp, rImagp, gainCache, TRUE, hHrtfParambin );
5022 : #else
5023 : hrtfShGetHrtf_fx( bin, aziDeg, eleDeg, lRealp, lImagp, rRealp, rImagp, gainCache, TRUE );
5024 : #endif
5025 : }
5026 : ELSE
5027 : {
5028 7385702 : gainCache->azi = aziDeg;
5029 7385702 : gainCache->ele = eleDeg;
5030 7385702 : move16();
5031 7385702 : move16();
5032 7385702 : IF( isHeadtracked )
5033 : {
5034 : // Word32 aziDeg_32, eleDeg_32;
5035 3309804 : rotateAziEle_fx( aziDeg, eleDeg, &aziDeg, &eleDeg, Rmat, 0 ); // need to be chnaged
5036 : // eleDeg = L_shr(eleDeg_32, 22);
5037 : // aziDeg = L_shr(aziDeg_32, 22);
5038 : }
5039 : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
5040 7385702 : hrtfShGetHrtf_fx( bin, aziDeg, eleDeg, lRealp, lImagp, rRealp, rImagp, gainCache, FALSE, hHrtfParambin );
5041 : #else
5042 : hrtfShGetHrtf_fx( bin, aziDeg, eleDeg, lRealp, lImagp, rRealp, rImagp, gainCache, FALSE );
5043 : #endif
5044 : }
5045 : }
5046 :
5047 20805489 : return;
5048 : }
5049 :
5050 19215743 : static void hrtfShGetHrtf_fx(
5051 : const Word16 bin,
5052 : const Word16 aziDeg,
5053 : const Word16 eleDeg,
5054 : Word32 *lRealp,
5055 : Word32 *lImagp,
5056 : Word32 *rRealp,
5057 : Word32 *rImagp,
5058 : PARAMBIN_HRTF_GAIN_CACHE *gainCache,
5059 : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
5060 : const Word16 useCachedValue,
5061 : HRTFS_PARAMBIN_HANDLE hHrtfParambin
5062 : #else
5063 : const Word16 useCachedValue
5064 : #endif
5065 : )
5066 : {
5067 : Word16 k;
5068 : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
5069 : Word16( *hrtfShCoeffsReInt_fx )[16][60];
5070 : Word16( *hrtfShCoeffsImInt_fx )[16][60];
5071 19215743 : hrtfShCoeffsReInt_fx = hHrtfParambin->hrtfShCoeffsRe_fx;
5072 19215743 : hrtfShCoeffsImInt_fx = hHrtfParambin->hrtfShCoeffsIm_fx;
5073 : #endif
5074 :
5075 19215743 : *lRealp = 0;
5076 19215743 : *lImagp = 0;
5077 19215743 : *rRealp = 0;
5078 19215743 : *rImagp = 0;
5079 19215743 : move32();
5080 19215743 : move32();
5081 19215743 : move32();
5082 19215743 : move32();
5083 :
5084 19215743 : IF( useCachedValue )
5085 : {
5086 : Word32 *shVec;
5087 11830041 : shVec = gainCache->shVec_fx;
5088 :
5089 201110697 : FOR( k = 0; k < HRTF_SH_CHANNELS; k++ )
5090 : {
5091 : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
5092 189280656 : *lRealp = Madd_32_16( *lRealp, shVec[k], hrtfShCoeffsReInt_fx[0][k][bin] ); // Q28
5093 189280656 : *lImagp = Madd_32_16( *lImagp, shVec[k], hrtfShCoeffsImInt_fx[0][k][bin] ); // Q28
5094 189280656 : *rRealp = Madd_32_16( *rRealp, shVec[k], hrtfShCoeffsReInt_fx[1][k][bin] ); // Q28
5095 189280656 : *rImagp = Madd_32_16( *rImagp, shVec[k], hrtfShCoeffsImInt_fx[1][k][bin] ); // Q28
5096 : #else
5097 : *lRealp = Madd_32_16( *lRealp, shVec[k], hrtfShCoeffsRe_fx[0][k][bin] ); // Q28
5098 : *lImagp = Madd_32_16( *lImagp, shVec[k], hrtfShCoeffsIm_fx[0][k][bin] ); // Q28
5099 : *rRealp = Madd_32_16( *rRealp, shVec[k], hrtfShCoeffsRe_fx[1][k][bin] ); // Q28
5100 : *rImagp = Madd_32_16( *rImagp, shVec[k], hrtfShCoeffsIm_fx[1][k][bin] ); // Q28
5101 : #endif
5102 189280656 : move32();
5103 189280656 : move32();
5104 189280656 : move32();
5105 189280656 : move32();
5106 : }
5107 : }
5108 : ELSE
5109 : {
5110 : Word32 shVec[HRTF_SH_CHANNELS];
5111 :
5112 7385702 : ivas_dirac_dec_get_response_fx( aziDeg,
5113 : eleDeg,
5114 : shVec,
5115 : HRTF_SH_ORDER,
5116 : Q29 );
5117 :
5118 125556934 : FOR( k = 0; k < HRTF_SH_CHANNELS; k++ )
5119 : {
5120 : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
5121 118171232 : *lRealp = Madd_32_16( *lRealp, shVec[k], hrtfShCoeffsReInt_fx[0][k][bin] ); // Q28
5122 118171232 : *lImagp = Madd_32_16( *lImagp, shVec[k], hrtfShCoeffsImInt_fx[0][k][bin] ); // Q28
5123 118171232 : *rRealp = Madd_32_16( *rRealp, shVec[k], hrtfShCoeffsReInt_fx[1][k][bin] ); // Q28
5124 118171232 : *rImagp = Madd_32_16( *rImagp, shVec[k], hrtfShCoeffsImInt_fx[1][k][bin] ); // Q28
5125 : #else
5126 : *lRealp = Madd_32_16( *lRealp, shVec[k], hrtfShCoeffsRe_fx[0][k][bin] ); // Q28
5127 : *lImagp = Madd_32_16( *lImagp, shVec[k], hrtfShCoeffsIm_fx[0][k][bin] ); // Q28
5128 : *rRealp = Madd_32_16( *rRealp, shVec[k], hrtfShCoeffsRe_fx[1][k][bin] ); // Q28
5129 : *rImagp = Madd_32_16( *rImagp, shVec[k], hrtfShCoeffsIm_fx[1][k][bin] ); // Q28
5130 : #endif
5131 118171232 : gainCache->shVec_fx[k] = shVec[k]; // Q29
5132 118171232 : move32();
5133 118171232 : move32();
5134 118171232 : move32();
5135 118171232 : move32();
5136 118171232 : move32();
5137 : }
5138 : }
5139 :
5140 19215743 : return;
5141 : }
5142 :
5143 : /*-------------------------------------------------------------------------
5144 : * configure_reqularization_factor()
5145 : *
5146 : * Configure regularization factor for the mixing matrix generation of the
5147 : * parametric binauralizer using IVAS codec format and current bitrate.
5148 : *------------------------------------------------------------------------*/
5149 :
5150 : /*! r: Configured reqularization factor value */
5151 :
5152 3541 : Word16 configure_reqularization_factor_fx(
5153 : const IVAS_FORMAT ivas_format, /* i : IVAS format */
5154 : const Word32 ivas_total_brate /* i : IVAS total bitrate */
5155 : )
5156 : {
5157 : Word16 reqularizationFactor;
5158 3541 : reqularizationFactor = 16384; /* Default value */ /*Q14*/
5159 3541 : move16();
5160 :
5161 3541 : IF( EQ_32( ivas_format, MASA_FORMAT ) )
5162 : {
5163 1708 : IF( GE_32( ivas_total_brate, IVAS_160k ) )
5164 : {
5165 144 : reqularizationFactor = 6553; /*Q14*/
5166 144 : move16();
5167 : }
5168 1564 : ELSE IF( EQ_32( ivas_total_brate, IVAS_128k ) )
5169 : {
5170 88 : reqularizationFactor = 8192; /*Q14*/
5171 88 : move16();
5172 : }
5173 1476 : ELSE IF( EQ_32( ivas_total_brate, IVAS_96k ) )
5174 : {
5175 96 : reqularizationFactor = 9830; /*Q14*/
5176 96 : move16();
5177 : }
5178 1380 : ELSE IF( GE_32( ivas_total_brate, IVAS_64k ) )
5179 : {
5180 202 : reqularizationFactor = 13107; /*Q14*/
5181 202 : move16();
5182 : }
5183 : ELSE
5184 : {
5185 1178 : reqularizationFactor = 16384; /*Q14*/
5186 1178 : move16();
5187 : }
5188 : }
5189 :
5190 3541 : IF( EQ_32( ivas_format, MC_FORMAT ) ) /* This is always McMASA for parametric binauralizer. */
5191 : {
5192 268 : IF( GE_32( ivas_total_brate, IVAS_96k ) )
5193 : {
5194 0 : reqularizationFactor = 6553; /*Q14*/
5195 0 : move16();
5196 : }
5197 268 : ELSE IF( GE_32( ivas_total_brate, IVAS_80k ) )
5198 : {
5199 2 : reqularizationFactor = 8192; /*Q14*/
5200 2 : move16();
5201 : }
5202 266 : ELSE IF( GE_32( ivas_total_brate, IVAS_64k ) )
5203 : {
5204 8 : reqularizationFactor = 11468; /*Q14*/
5205 8 : move16();
5206 : }
5207 258 : ELSE IF( GE_32( ivas_total_brate, IVAS_48k ) )
5208 : {
5209 13 : reqularizationFactor = 13107; /*Q14*/
5210 13 : move16();
5211 : }
5212 : ELSE
5213 : {
5214 245 : reqularizationFactor = 16384; /*Q14*/
5215 245 : move16();
5216 : }
5217 : }
5218 :
5219 : /* For SBA and parametric ISM, currently in default value of 1.0f. */
5220 :
5221 3541 : return reqularizationFactor;
5222 : }
5223 :
5224 : /*-------------------------------------------------------------------*
5225 : * ivas_omasa_preProcessStereoTransportsForMovedObjects_fx()
5226 : *
5227 : *
5228 : *-------------------------------------------------------------------*/
5229 :
5230 5053 : void ivas_omasa_preProcessStereoTransportsForMovedObjects_fx(
5231 : Decoder_Struct *st_ivas,
5232 : Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*cldfb_buf_q*/
5233 : Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*cldfb_buf_q*/
5234 : Word16 *cldfb_buf_q,
5235 : const Word16 nBins,
5236 : const Word16 subframe )
5237 : {
5238 : Word16 bin, ch, inCh, outCh, ismDirIndex, slot;
5239 : SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom;
5240 : MASA_ISM_DATA_HANDLE hMasaIsmData;
5241 : UWord8 enableCentering;
5242 : Word16 dirac_read_idx;
5243 : Word16 nSlots;
5244 :
5245 5053 : hSpatParamRendCom = st_ivas->hSpatParamRendCom;
5246 5053 : hMasaIsmData = st_ivas->hMasaIsmData;
5247 :
5248 5053 : test();
5249 5053 : test();
5250 5053 : IF( EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_FOA ) || EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_HOA2 ) || EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_HOA3 ) )
5251 : {
5252 1216 : enableCentering = 0;
5253 1216 : move16();
5254 : }
5255 : ELSE
5256 : {
5257 3837 : enableCentering = 1;
5258 3837 : move16();
5259 : }
5260 :
5261 : /* Bypass processing until first object is moved */
5262 5053 : IF( hMasaIsmData->objectsMoved == 0 )
5263 : {
5264 21203 : FOR( ismDirIndex = 0; ismDirIndex < hSpatParamRendCom->numIsmDirections; ismDirIndex++ )
5265 : {
5266 16150 : if ( hMasaIsmData->ism_is_edited[ismDirIndex] )
5267 : {
5268 0 : hMasaIsmData->objectsMoved = 1;
5269 0 : move16();
5270 : }
5271 : }
5272 5053 : IF( hMasaIsmData->objectsMoved == 0 )
5273 : {
5274 : /* No objects have moved so far */
5275 5053 : return;
5276 : }
5277 : }
5278 :
5279 : /* Perform object-movement based processing */
5280 0 : nSlots = hSpatParamRendCom->subframe_nbslots[subframe];
5281 0 : move16();
5282 0 : dirac_read_idx = hSpatParamRendCom->render_to_md_map[subframe];
5283 0 : move16();
5284 :
5285 0 : FOR( bin = 0; bin < nBins; bin++ )
5286 : {
5287 : Word16 ismPreprocMtxNew_fx[2][2];
5288 : Word16 ismPreprocMtxIncrement_fx[2][2];
5289 : Word16 eneMove_fx[2];
5290 : Word16 enePreserve_fx[2];
5291 : Word16 ismRatioAcc_fx;
5292 : Word32 subframeEne_fx;
5293 : Word32 Enes_fx[2];
5294 : Word16 normEnes_fx[2];
5295 : Word16 remainderNormEne_fx;
5296 0 : Word16 normEnes_q_fx[2], temp_q = 0;
5297 : Word16 eneMove_q_fx[2], enePreserve_q_fx[2], temp1;
5298 : Word32 temp;
5299 :
5300 0 : set16_fx( ismPreprocMtxNew_fx[0], 0, 2 );
5301 0 : set16_fx( ismPreprocMtxNew_fx[1], 0, 2 );
5302 0 : set16_fx( ismPreprocMtxIncrement_fx[0], 0, 2 );
5303 0 : set16_fx( ismPreprocMtxIncrement_fx[1], 0, 2 );
5304 0 : set16_fx( eneMove_fx, 0, 2 );
5305 0 : set16_fx( enePreserve_fx, 0, 2 );
5306 0 : ismRatioAcc_fx = 0;
5307 0 : move16();
5308 0 : subframeEne_fx = 0;
5309 0 : move32();
5310 0 : set16_fx( normEnes_fx, 0, 2 );
5311 0 : set32_fx( Enes_fx, 0, 2 );
5312 0 : set16_fx( normEnes_q_fx, Q31, 2 );
5313 0 : set16_fx( eneMove_q_fx, Q31, 2 );
5314 0 : set16_fx( enePreserve_q_fx, Q31, 2 );
5315 :
5316 : /* Determine transport normalized energies and subframe energy */
5317 0 : FOR( slot = 0; slot < nSlots; slot++ )
5318 : {
5319 0 : FOR( ch = 0; ch < 2; ch++ )
5320 : {
5321 0 : Enes_fx[ch] = L_add( Enes_fx[ch], Mpy_32_32( inRe_fx[ch][slot][bin], inRe_fx[ch][slot][bin] ) ); // Q = *cldfb_buf_q + *cldfb_buf_q - 31 = Q-19
5322 0 : move32();
5323 0 : Enes_fx[ch] = L_add( Enes_fx[ch], Mpy_32_32( inIm_fx[ch][slot][bin], inIm_fx[ch][slot][bin] ) ); // Q = *cldfb_buf_q + *cldfb_buf_q - 31 = Q-19
5324 0 : move32();
5325 : }
5326 :
5327 0 : subframeEne_fx = L_add( Enes_fx[0], Enes_fx[1] ); // Q = *cldfb_buf_q + *cldfb_buf_q - 31 = Q-19
5328 :
5329 0 : IF( subframeEne_fx != 0 )
5330 : {
5331 0 : normEnes_fx[0] = BASOP_Util_Divide3232_Scale( Enes_fx[0], subframeEne_fx, &temp_q );
5332 0 : move32();
5333 0 : normEnes_fx[0] = shr( normEnes_fx[0], sub( sub( 15, temp_q ), Q12 ) ); // Q12
5334 0 : move32();
5335 0 : normEnes_fx[1] = BASOP_Util_Divide3232_Scale( Enes_fx[1], subframeEne_fx, &temp_q );
5336 0 : move32();
5337 0 : normEnes_fx[1] = shr( normEnes_fx[1], sub( sub( 15, temp_q ), Q12 ) ); // Q12
5338 0 : move32();
5339 : }
5340 : ELSE
5341 : {
5342 0 : normEnes_fx[0] = BASOP_Util_Divide3232_Scale( Enes_fx[0], EPSILON_FX, &temp_q );
5343 0 : move32();
5344 0 : normEnes_fx[0] = shr( normEnes_fx[0], sub( sub( 15, temp_q ), Q12 ) ); // Q12
5345 0 : move32();
5346 0 : normEnes_fx[1] = BASOP_Util_Divide3232_Scale( Enes_fx[1], EPSILON_FX, &temp_q );
5347 0 : move32();
5348 0 : normEnes_fx[1] = shr( normEnes_fx[1], sub( sub( 15, temp_q ), Q12 ) ); // Q12
5349 0 : move32();
5350 : }
5351 :
5352 :
5353 : /* For each ismDir, formulate a mix-matrix that moves object audio signals between
5354 : * left and right channels when needed. Make a combined matrix by a ratio-weighted sum */
5355 0 : FOR( ismDirIndex = 0; ismDirIndex < hSpatParamRendCom->numIsmDirections; ismDirIndex++ )
5356 : {
5357 : Word16 panGainsOut_fx[2];
5358 : Word16 panGainsIn_fx[2];
5359 : Word16 ratio;
5360 : Word16 panEnesOut_fx[2];
5361 : Word16 panEnesIn_fx[2];
5362 : Word16 centeringFactor_fx;
5363 :
5364 0 : ratio = extract_l( hMasaIsmData->energy_ratio_ism_fx[ismDirIndex][dirac_read_idx][bin] ); // Q14
5365 0 : ismRatioAcc_fx = add( ismRatioAcc_fx, ratio );
5366 :
5367 : /* Get input and output panning gains */
5368 0 : ivas_get_stereo_panning_gains_fx( hMasaIsmData->azimuth_ism[ismDirIndex][dirac_read_idx],
5369 0 : hMasaIsmData->elevation_ism[ismDirIndex][dirac_read_idx],
5370 : panGainsIn_fx );
5371 :
5372 0 : IF( hMasaIsmData->ism_is_edited[ismDirIndex] )
5373 : {
5374 0 : ivas_get_stereo_panning_gains_fx( hMasaIsmData->azimuth_ism_edited[ismDirIndex],
5375 0 : hMasaIsmData->elevation_ism_edited[ismDirIndex],
5376 : panGainsOut_fx );
5377 : }
5378 : ELSE
5379 : {
5380 : /* When not edited, input and output pan gains are the same */
5381 0 : FOR( ch = 0; ch < 2; ch++ )
5382 : {
5383 0 : panGainsOut_fx[ch] = panGainsIn_fx[ch];
5384 0 : move16();
5385 : }
5386 : }
5387 :
5388 : /* Determine pan enes */
5389 0 : FOR( ch = 0; ch < 2; ch++ )
5390 : {
5391 0 : panEnesOut_fx[ch] = mult( panGainsOut_fx[ch], panGainsOut_fx[ch] ); // Q15
5392 0 : move16();
5393 0 : panEnesIn_fx[ch] = mult( panGainsIn_fx[ch], panGainsIn_fx[ch] ); // Q15
5394 0 : move16();
5395 : }
5396 :
5397 0 : IF( enableCentering )
5398 : {
5399 0 : centeringFactor_fx = s_max( 0, sub( mult( shl( 2, 13 ), abs_s( sub( panEnesIn_fx[0], panEnesOut_fx[0] ) ) ), ONE_IN_Q13 ) ); // Q13
5400 0 : FOR( ch = 0; ch < 2; ch++ )
5401 : {
5402 0 : panEnesOut_fx[ch] = mult( panEnesOut_fx[ch], sub( ONE_IN_Q13, centeringFactor_fx ) ); // Q13
5403 0 : move16();
5404 0 : panEnesOut_fx[ch] = add( panEnesOut_fx[ch], shr( centeringFactor_fx, 1 ) ); // Q13
5405 0 : move16();
5406 : }
5407 : }
5408 :
5409 0 : FOR( ch = 0; ch < 2; ch++ )
5410 : {
5411 : Word16 eneMoveThis_fx;
5412 : Word16 enePreserveThis_fx;
5413 :
5414 0 : eneMoveThis_fx = s_max( 0, sub( shr( panEnesIn_fx[ch], 2 ), panEnesOut_fx[ch] ) ); // Q13
5415 0 : enePreserveThis_fx = sub( shr( panEnesIn_fx[ch], 2 ), eneMoveThis_fx ); // Q13
5416 :
5417 0 : eneMove_fx[ch] = mult( ratio, eneMoveThis_fx ); // Q = 14 + 13 - 15 = 12
5418 0 : move16();
5419 0 : enePreserve_fx[ch] = mult( ratio, enePreserveThis_fx ); // Q = 14 + 13 - 15 = 12
5420 0 : move16();
5421 :
5422 : /* Subtract object parts from normEnes */
5423 0 : normEnes_fx[ch] = sub( normEnes_fx[ch], shr( mult( panEnesIn_fx[ch], ratio ), 2 ) ); // Q12
5424 0 : move16();
5425 : }
5426 : }
5427 :
5428 : /* Any remaining (non-object) energy is set to be preserved at both channels */
5429 0 : remainderNormEne_fx = s_max( 0, sub( sub( shr( sub( ONE_IN_Q14, ismRatioAcc_fx ), Q14 - Q12 ), normEnes_fx[0] ), normEnes_fx[1] ) ); // Q12
5430 :
5431 0 : FOR( ch = 0; ch < 2; ch++ )
5432 : {
5433 0 : enePreserve_fx[ch] = add( enePreserve_fx[ch], s_max( 0, add( enePreserve_fx[ch], shr( remainderNormEne_fx, 1 ) ) ) ); // Q12
5434 0 : move16();
5435 : }
5436 :
5437 : /* Temporally average energy moving and preserving, and generate the transport signal preprocessing matrix */
5438 0 : FOR( ch = 0; ch < 2; ch++ )
5439 : {
5440 : Word32 normVal_fx;
5441 0 : hMasaIsmData->eneMoveIIR_fx[ch][bin] = Mpy_32_16_1( hMasaIsmData->eneMoveIIR_fx[ch][bin], STEREO_PREPROCESS_IIR_FACTOR_Q15 );
5442 0 : move32();
5443 0 : temp = Mpy_32_16_1( subframeEne_fx, eneMove_fx[ch] );
5444 0 : hMasaIsmData->eneMoveIIR_fx[ch][bin] = L_add( hMasaIsmData->eneMoveIIR_fx[ch][bin], temp ); // Q = *cldfb_buf_q + *cldfb_buf_q - 34 = Q-22
5445 0 : move32();
5446 :
5447 0 : hMasaIsmData->enePreserveIIR_fx[ch][bin] = Mpy_32_16_1( hMasaIsmData->enePreserveIIR_fx[ch][bin], STEREO_PREPROCESS_IIR_FACTOR_Q15 );
5448 0 : move32();
5449 0 : temp = Mpy_32_16_1( subframeEne_fx, enePreserve_fx[ch] );
5450 0 : hMasaIsmData->enePreserveIIR_fx[ch][bin] = L_add( hMasaIsmData->enePreserveIIR_fx[ch][bin], temp ); // Q = *cldfb_buf_q + *cldfb_buf_q - 34 = Q-22
5451 0 : move32();
5452 :
5453 0 : normVal_fx = L_add( hMasaIsmData->eneMoveIIR_fx[ch][bin], hMasaIsmData->enePreserveIIR_fx[ch][bin] );
5454 0 : IF( normVal_fx != 0 )
5455 : {
5456 :
5457 0 : temp1 = BASOP_Util_Divide3232_Scale( hMasaIsmData->enePreserveIIR_fx[ch][bin], normVal_fx, &temp_q );
5458 0 : ismPreprocMtxNew_fx[ch][ch] = Sqrt16( temp1, &temp_q );
5459 0 : move16();
5460 0 : ismPreprocMtxNew_fx[ch][ch] = shl( ismPreprocMtxNew_fx[ch][ch], temp_q ); // Q15
5461 0 : move16();
5462 0 : temp1 = BASOP_Util_Divide3232_Scale( hMasaIsmData->eneMoveIIR_fx[ch][bin], normVal_fx, &temp_q );
5463 0 : ismPreprocMtxNew_fx[sub( 1, ch )][ch] = Sqrt16( temp1, &temp_q );
5464 0 : move16();
5465 0 : ismPreprocMtxNew_fx[sub( 1, ch )][ch] = shl( ismPreprocMtxNew_fx[sub( 1, ch )][ch], temp_q ); // Q15
5466 0 : move16();
5467 : }
5468 : ELSE
5469 : {
5470 0 : ismPreprocMtxNew_fx[ch][ch] = 0;
5471 0 : move16();
5472 0 : ismPreprocMtxNew_fx[sub( 1, ch )][ch] = 0;
5473 0 : move16();
5474 : }
5475 : }
5476 :
5477 : /* Get increment value for temporal interpolation */
5478 0 : FOR( inCh = 0; inCh < 2; inCh++ )
5479 : {
5480 0 : FOR( outCh = 0; outCh < 2; outCh++ )
5481 0 : ismPreprocMtxIncrement_fx[outCh][inCh] = BASOP_Util_Divide1616_Scale( sub( ismPreprocMtxNew_fx[outCh][inCh], hMasaIsmData->ismPreprocMatrix_fx[outCh][inCh][bin] ), nSlots, &temp_q );
5482 0 : move16();
5483 0 : ismPreprocMtxIncrement_fx[outCh][inCh] = shl( ismPreprocMtxIncrement_fx[outCh][inCh], temp_q ); // Q15
5484 0 : move16();
5485 : }
5486 : }
5487 :
5488 : /* Mix signals */
5489 0 : FOR( slot = 0; slot < nSlots; slot++ )
5490 : {
5491 0 : Word16 eqVal_fx = 0;
5492 0 : Word16 eqVal_q_fx = 0;
5493 0 : move16();
5494 0 : move16();
5495 : Word32 outSlotRe_fx[2];
5496 : Word32 outSlotIm_fx[2];
5497 :
5498 0 : set_zero_fx( outSlotRe_fx, 2 );
5499 0 : set_zero_fx( outSlotIm_fx, 2 );
5500 :
5501 0 : FOR( outCh = 0; outCh < 2; outCh++ )
5502 : {
5503 0 : FOR( inCh = 0; inCh < 2; inCh++ )
5504 : {
5505 0 : hMasaIsmData->ismPreprocMatrix_fx[outCh][inCh][bin] = add( hMasaIsmData->ismPreprocMatrix_fx[outCh][inCh][bin], ismPreprocMtxIncrement_fx[outCh][inCh] ); // Q = 15
5506 0 : move16();
5507 0 : outSlotRe_fx[outCh] = Mpy_32_16_1( inRe_fx[inCh][slot][bin], hMasaIsmData->ismPreprocMatrix_fx[outCh][inCh][bin] ); // Q = *cldfb_buf_q;
5508 0 : move32();
5509 0 : outSlotIm_fx[outCh] = Mpy_32_16_1( inIm_fx[inCh][slot][bin], hMasaIsmData->ismPreprocMatrix_fx[outCh][inCh][bin] ); // Q = *cldfb_buf_q;
5510 0 : move32();
5511 : }
5512 : }
5513 :
5514 : /* IIR average the energy measures and determine and apply energy-preserving equalizer */
5515 0 : hMasaIsmData->preprocEneTarget_fx[bin] = Mpy_32_16_1( hMasaIsmData->preprocEneTarget_fx[bin], STEREO_PREPROCESS_IIR_FACTOR_Q15 );
5516 0 : move32();
5517 0 : hMasaIsmData->preprocEneRealized_fx[bin] = Mpy_32_16_1( hMasaIsmData->preprocEneRealized_fx[bin], STEREO_PREPROCESS_IIR_FACTOR_Q15 );
5518 0 : move32();
5519 0 : FOR( ch = 0; ch < 2; ch++ )
5520 : {
5521 0 : hMasaIsmData->preprocEneTarget_fx[bin] = L_add( hMasaIsmData->preprocEneTarget_fx[bin], Madd_32_32( Mpy_32_32( inRe_fx[ch][slot][bin], inRe_fx[ch][slot][bin] ), inIm_fx[ch][slot][bin], inIm_fx[ch][slot][bin] ) ); // Q= *cldfb_buf_q + *cldfb_buf_q - 31 = Q-19
5522 0 : move32();
5523 0 : hMasaIsmData->preprocEneRealized_fx[bin] = L_add( hMasaIsmData->preprocEneRealized_fx[bin], Madd_32_32( Mpy_32_32( outSlotRe_fx[ch], outSlotRe_fx[ch] ), outSlotIm_fx[ch], outSlotIm_fx[ch] ) ); // Q= *cldfb_buf_q + *cldfb_buf_q - 31 = Q-19
5524 0 : move32();
5525 : }
5526 0 : temp1 = BASOP_Util_Divide3232_Scale( hMasaIsmData->preprocEneTarget_fx[bin], L_max( EPSILON_FX, hMasaIsmData->preprocEneRealized_fx[bin] ), &eqVal_q_fx );
5527 0 : eqVal_fx = Sqrt16( temp1, &eqVal_q_fx );
5528 0 : temp1 = 4 << Q12; // Q12
5529 0 : move16();
5530 0 : IF( LT_16( eqVal_q_fx, Q12 ) )
5531 : {
5532 0 : IF( GT_16( eqVal_fx, shr( temp1, sub( Q12, eqVal_q_fx ) ) ) )
5533 : {
5534 0 : eqVal_fx = temp1;
5535 0 : move16();
5536 0 : eqVal_q_fx = Q12;
5537 0 : move16();
5538 : }
5539 : }
5540 : ELSE
5541 : {
5542 0 : if ( GT_16( shr( eqVal_fx, sub( eqVal_q_fx, Q12 ) ), temp1 ) )
5543 : {
5544 0 : eqVal_fx = temp1; // eqVal_q_fx
5545 0 : move16();
5546 : }
5547 : }
5548 :
5549 0 : FOR( ch = 0; ch < 2; ch++ )
5550 : {
5551 0 : inRe_fx[ch][slot][bin] = Mpy_32_16_1( outSlotRe_fx[ch], eqVal_fx );
5552 0 : move32();
5553 0 : inIm_fx[ch][slot][bin] = Mpy_32_16_1( outSlotIm_fx[ch], eqVal_fx );
5554 0 : move32();
5555 : }
5556 0 : *cldfb_buf_q = sub( add( *cldfb_buf_q, eqVal_q_fx ), 15 );
5557 0 : move16();
5558 : }
5559 : }
5560 :
5561 0 : return;
5562 : }
5563 :
5564 :
5565 7200 : static void ivas_masa_ext_rend_parambin_internal_fx(
5566 : MASA_EXT_REND_HANDLE hMasaExtRend,
5567 : COMBINED_ORIENTATION_HANDLE hCombinedOrientationData,
5568 : Word32 *output_fx[], /* Q11*/
5569 : const Word16 subframe,
5570 : const SPLIT_REND_WRAPPER *hSplitRendWrapper,
5571 : Word32 Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
5572 : Word32 Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] )
5573 : {
5574 : DIRAC_DEC_BIN_HANDLE hDiracDecBin;
5575 : SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom;
5576 : PARAMBIN_REND_CONFIG config_data;
5577 : Word16 slot, ch, numInChannels;
5578 : Word16 max_band_decorr;
5579 : Word16 nBins;
5580 : Word16 i, j;
5581 : Word16 nchan_transport;
5582 : Word16 q_mat;
5583 : int16_t pos_idx;
5584 : const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData;
5585 : Word32 tmp_Cldfb_out_re[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
5586 : Word32 tmp_Cldfb_out_im[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
5587 :
5588 : /* 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 */
5589 : Word32 reverbRe_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
5590 : Word32 reverbIm_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
5591 : Word32 decorrRe_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
5592 : Word32 decorrIm_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
5593 : Word32 subFrameTotalEne_fx[CLDFB_NO_CHANNELS_MAX];
5594 : Word16 subFrameTotalEne_e[CLDFB_NO_CHANNELS_MAX];
5595 : Word32 IIReneLimiter_fx[CLDFB_NO_CHANNELS_MAX];
5596 : Word16 Q_inp_mix;
5597 :
5598 7200 : hDiracDecBin = hMasaExtRend->hDiracDecBin[0];
5599 7200 : hSpatParamRendCom = hMasaExtRend->hSpatParamRendCom;
5600 :
5601 : Word32 Cldfb_RealBuffer_in_fx[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
5602 : Word32 Cldfb_ImagBuffer_in_fx[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
5603 :
5604 50400 : FOR( i = 0; i < 6; i++ )
5605 : {
5606 216000 : FOR( j = 0; j < CLDFB_SLOTS_PER_SUBFRAME; j++ )
5607 : {
5608 172800 : set32_fx( Cldfb_RealBuffer_in_fx[i][j], 0, CLDFB_NO_CHANNELS_MAX );
5609 172800 : set32_fx( Cldfb_ImagBuffer_in_fx[i][j], 0, CLDFB_NO_CHANNELS_MAX );
5610 : }
5611 : }
5612 : Word32 Rmat_fx[3][3];
5613 7200 : hDiracDecBin = hMasaExtRend->hDiracDecBin[0];
5614 7200 : assert( hDiracDecBin );
5615 7200 : hSpatParamRendCom = hMasaExtRend->hSpatParamRendCom;
5616 7200 : nBins = hSpatParamRendCom->num_freq_bands;
5617 :
5618 : /* Setup internal config. MASA EXT renderer is quite strict. */
5619 7200 : config_data.separateCenterChannelRendering = 0;
5620 7200 : move16();
5621 7200 : config_data.ivas_format = MASA_FORMAT;
5622 7200 : move32();
5623 7200 : config_data.mc_mode = MC_MODE_NONE;
5624 7200 : move32();
5625 7200 : config_data.ivas_total_brate = IVAS_512k; /* Maximum bitrate set for external renderer */
5626 7200 : move32();
5627 7200 : config_data.nchan_transport = hMasaExtRend->nchan_input;
5628 7200 : move16();
5629 7200 : config_data.qualityBasedSmFactor_fx = ONE_IN_Q31;
5630 7200 : move32();
5631 7200 : IF( EQ_16( hMasaExtRend->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) )
5632 : {
5633 0 : config_data.processReverb = 1;
5634 0 : move16();
5635 : }
5636 : ELSE
5637 : {
5638 7200 : config_data.processReverb = 0;
5639 7200 : move16();
5640 : }
5641 7200 : config_data.ism_mode = ISM_MODE_NONE;
5642 7200 : move32();
5643 :
5644 : /* Set nchan_transport to number of transport channels in MASA input */
5645 7200 : nchan_transport = hMasaExtRend->nchan_input;
5646 7200 : move16();
5647 :
5648 : /* The input channel number at this processing function (not nchan_transport) */
5649 7200 : numInChannels = BINAURAL_CHANNELS;
5650 7200 : move16();
5651 :
5652 7200 : Rmat_fx[0][0] = ONE_IN_Q30;
5653 7200 : Rmat_fx[0][1] = 0;
5654 7200 : Rmat_fx[0][2] = 0;
5655 7200 : move32();
5656 7200 : move32();
5657 7200 : move32();
5658 :
5659 7200 : Rmat_fx[1][0] = 0;
5660 7200 : Rmat_fx[1][1] = ONE_IN_Q30;
5661 7200 : Rmat_fx[1][2] = 0;
5662 7200 : move32();
5663 7200 : move32();
5664 7200 : move32();
5665 :
5666 7200 : Rmat_fx[2][0] = 0;
5667 7200 : Rmat_fx[2][1] = 0;
5668 7200 : Rmat_fx[2][2] = ONE_IN_Q30;
5669 7200 : move32();
5670 7200 : move32();
5671 7200 : move32();
5672 :
5673 : /* CLDFB Analysis of input */
5674 :
5675 36000 : FOR( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ )
5676 : {
5677 86400 : FOR( ch = 0; ch < numInChannels; ch++ )
5678 : {
5679 57600 : test();
5680 57600 : IF( ch == 0 || EQ_16( nchan_transport, 2 ) )
5681 43200 : {
5682 43200 : Word16 q_cldfb = Q11;
5683 43200 : move16();
5684 43200 : cldfbAnalysis_ts_fx_fixed_q(
5685 43200 : &( output_fx[ch][nBins * slot] ),
5686 43200 : Cldfb_RealBuffer_in_fx[ch][slot],
5687 43200 : Cldfb_ImagBuffer_in_fx[ch][slot],
5688 : nBins, hMasaExtRend->cldfbAnaRend[ch], &q_cldfb );
5689 : }
5690 : ELSE /* when nchan_transport == 1 and ch == 1 */
5691 : {
5692 : /* At mono input duplicate the channel to dual-mono, and apply gain
5693 : correction to ensure same overall level as in stereo mode */
5694 14400 : v_multc_fixed( Cldfb_RealBuffer_in_fx[0][slot], 1518500224 /* INV_SQRT_2 in Q31 */, Cldfb_RealBuffer_in_fx[0][slot], nBins );
5695 14400 : v_multc_fixed( Cldfb_ImagBuffer_in_fx[0][slot], 1518500224 /* INV_SQRT_2 in Q31 */, Cldfb_ImagBuffer_in_fx[0][slot], nBins );
5696 :
5697 14400 : Copy32( Cldfb_RealBuffer_in_fx[0][slot], Cldfb_RealBuffer_in_fx[1][slot], nBins );
5698 14400 : Copy32( Cldfb_ImagBuffer_in_fx[0][slot], Cldfb_ImagBuffer_in_fx[1][slot], nBins );
5699 : }
5700 : }
5701 : }
5702 7200 : Word16 q_inp = Q6;
5703 7200 : move16();
5704 7200 : IF( hCombinedOrientationData )
5705 : {
5706 9600 : FOR( i = 0; i < 3; i++ )
5707 : {
5708 28800 : FOR( j = 0; j < 3; j++ )
5709 : {
5710 21600 : Rmat_fx[i][j] = hCombinedOrientationData->Rmat_fx[hCombinedOrientationData->subframe_idx][i][j]; // Q30//
5711 21600 : move32();
5712 : }
5713 : }
5714 :
5715 2400 : IF( EQ_16( nchan_transport, 2 ) )
5716 : {
5717 : /* in case of split rendering, determine the prototype rotation based on the main direction and use the same prototypes for the offset directions */
5718 1200 : adaptTransportSignalsHeadtracked_fx( hCombinedOrientationData, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat_fx );
5719 1200 : ivas_dirac_dec_binaural_check_and_switch_transports_headtracked_fx( hCombinedOrientationData, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat_fx );
5720 : }
5721 : }
5722 :
5723 7200 : test();
5724 : /* Always using CLDFB decorrelation in MASA EXT renderer */
5725 7200 : max_band_decorr = hDiracDecBin->h_freq_domain_decorr_ap_params->max_band_decorr;
5726 :
5727 7200 : ivas_dirac_dec_binaural_formulate_input_covariance_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, subframe,
5728 : subFrameTotalEne_fx, subFrameTotalEne_e, IIReneLimiter_fx, q_inp );
5729 7200 : ivas_dirac_dec_binaural_formulate_target_covariance_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat_fx, subframe,
5730 7200 : hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0,
5731 : subFrameTotalEne_fx, subFrameTotalEne_e, IIReneLimiter_fx, NULL );
5732 :
5733 7200 : ivas_dirac_dec_binaural_determine_processing_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat_fx, subframe,
5734 7200 : hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0,
5735 : 0, NULL );
5736 :
5737 : Word16 q_out;
5738 7200 : q_inp = Q6;
5739 7200 : move16();
5740 :
5741 21600 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
5742 : {
5743 14400 : hMasaExtRend->cldfbSynRend[ch]->Q_cldfb_state = Q11;
5744 14400 : move16();
5745 : }
5746 :
5747 7200 : q_mat = hDiracDecBin->q_processMtx;
5748 7200 : move16();
5749 7200 : q_mat = s_min( q_mat, hDiracDecBin->q_processMtxPrev );
5750 7200 : q_mat = s_min( q_mat, hDiracDecBin->q_processMtxDec );
5751 7200 : q_mat = s_min( q_mat, hDiracDecBin->q_processMtxDecPrev );
5752 :
5753 21600 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
5754 : {
5755 43200 : FOR( slot = 0; slot < BINAURAL_CHANNELS; slot++ )
5756 : {
5757 28800 : Scale_sig( hDiracDecBin->processMtxDecRe_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDec ) ); // scaling to q_mat
5758 28800 : Scale_sig( hDiracDecBin->processMtxDecIm_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDec ) ); // scaling to q_mat
5759 28800 : Scale_sig( hDiracDecBin->processMtxDecRePrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDecPrev ) ); // scaling to q_mat
5760 28800 : Scale_sig( hDiracDecBin->processMtxDecImPrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDecPrev ) ); // scaling to q_mat
5761 : }
5762 : }
5763 21600 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
5764 : {
5765 43200 : FOR( slot = 0; slot < numInChannels; slot++ )
5766 : {
5767 28800 : Scale_sig( hDiracDecBin->processMtxRe_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) ); // scaling to q_mat
5768 28800 : Scale_sig( hDiracDecBin->processMtxIm_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) ); // scaling to q_mat
5769 28800 : Scale_sig( hDiracDecBin->processMtxRePrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); // scaling to q_mat
5770 28800 : Scale_sig( hDiracDecBin->processMtxImPrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); // scaling to q_mat
5771 : }
5772 : }
5773 7200 : hDiracDecBin->q_processMtx = q_mat;
5774 7200 : hDiracDecBin->q_processMtxPrev = q_mat;
5775 7200 : hDiracDecBin->q_processMtxDec = q_mat;
5776 7200 : hDiracDecBin->q_processMtxDecPrev = q_mat;
5777 7200 : move16();
5778 7200 : move16();
5779 7200 : move16();
5780 7200 : move16();
5781 :
5782 7200 : pMultiBinPoseData = NULL;
5783 7200 : if ( hSplitRendWrapper != NULL )
5784 : {
5785 0 : pMultiBinPoseData = &( hSplitRendWrapper->multiBinPoseData );
5786 :
5787 0 : ivas_dirac_dec_binaural_process_output_fx( hDiracDecBin, hSpatParamRendCom, hMasaExtRend->cldfbSynRend, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat, tmp_Cldfb_out_re, tmp_Cldfb_out_im,
5788 : reverbRe_fx, reverbIm_fx, decorrRe_fx, decorrIm_fx, &Q_inp_mix, 1 );
5789 :
5790 0 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
5791 : {
5792 0 : for ( i = 0; i < CLDFB_SLOTS_PER_SUBFRAME; i++ )
5793 : {
5794 0 : Copy32( tmp_Cldfb_out_re[ch][i], Cldfb_Out_Real[ch][subframe * CLDFB_SLOTS_PER_SUBFRAME + i], CLDFB_NO_CHANNELS_MAX );
5795 0 : Copy32( tmp_Cldfb_out_im[ch][i], Cldfb_Out_Imag[ch][subframe * CLDFB_SLOTS_PER_SUBFRAME + i], CLDFB_NO_CHANNELS_MAX );
5796 : }
5797 : }
5798 : }
5799 : else
5800 : {
5801 7200 : ivas_dirac_dec_binaural_process_output_fx( hDiracDecBin, hSpatParamRendCom, hMasaExtRend->cldfbSynRend, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat, NULL, NULL,
5802 : reverbRe_fx, reverbIm_fx, decorrRe_fx, decorrIm_fx, &Q_inp_mix, 1 );
5803 : }
5804 :
5805 7200 : hDiracDecBin->hDiffuseDist = NULL;
5806 :
5807 7200 : if ( pMultiBinPoseData != NULL && pMultiBinPoseData->num_poses > 1 )
5808 : {
5809 : /* quaternion-based rotation from ivas_binRenderer_internal.c:ivas_binRenderer(), but using absolute rotation instead of delta rotations */
5810 : IVAS_QUATERNION Quaternions_rot, Quaternions_abs, *Quaternions_ref;
5811 : Word32 Rmat_local[3][3];
5812 :
5813 :
5814 0 : if ( hCombinedOrientationData )
5815 : {
5816 0 : Quaternions_ref = &hCombinedOrientationData->Quaternions[0];
5817 0 : Copy_Quat_fx( Quaternions_ref, &Quaternions_abs );
5818 0 : modify_Quat_q_fx( &Quaternions_abs, &Quaternions_abs, Q22 );
5819 0 : Quaternions_rot.w_fx = L_negate( 12582912 ); /* signal to use Euler */
5820 0 : Quat2EulerDegree_fx( Quaternions_abs, &Quaternions_abs.z_fx, &Quaternions_abs.y_fx, &Quaternions_abs.x_fx ); /*order in Quat2Euler seems to be reversed ?*/
5821 0 : Quaternions_abs.w_fx = L_negate( 12582912 ); /* signal to use Euler */
5822 :
5823 0 : FOR( pos_idx = 1; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ )
5824 : {
5825 0 : Quaternions_rot.x_fx = L_add( Quaternions_abs.x_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][0] );
5826 0 : Quaternions_rot.y_fx = L_add( Quaternions_abs.y_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][1] );
5827 0 : Quaternions_rot.z_fx = L_add( Quaternions_abs.z_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][2] );
5828 0 : move32();
5829 0 : move32();
5830 0 : move32();
5831 0 : Euler2Quat_fx( deg2rad_fx( Quaternions_rot.x_fx ), deg2rad_fx( Quaternions_rot.y_fx ), deg2rad_fx( Quaternions_rot.z_fx ), &Quaternions_rot );
5832 0 : modify_Quat_q_fx( &Quaternions_rot, &Quaternions_rot, Quaternions_ref->q_fact );
5833 0 : QuatToRotMat_fx( Quaternions_rot, Rmat_local );
5834 0 : modify_Rmat_q_fx( Rmat_local, Rmat_local, sub( shl( Quaternions_ref->q_fact, 1 ), 32 ), Q30 );
5835 :
5836 0 : hDiracDecBin = hMasaExtRend->hDiracDecBin[pos_idx];
5837 0 : assert( hDiracDecBin != NULL && "No DiracDecBin handle for this position" );
5838 :
5839 : /* re-use input covariance for the side renderings */
5840 0 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
5841 : {
5842 0 : Copy32( hMasaExtRend->hDiracDecBin[0]->ChEne_fx[ch], hDiracDecBin->ChEne_fx[ch], hSpatParamRendCom->num_freq_bands );
5843 0 : Copy( hMasaExtRend->hDiracDecBin[0]->ChEne_e[ch], hDiracDecBin->ChEne_e[ch], hSpatParamRendCom->num_freq_bands );
5844 : }
5845 0 : Copy32( hMasaExtRend->hDiracDecBin[0]->ChCrossRe_fx, hDiracDecBin->ChCrossRe_fx, hSpatParamRendCom->num_freq_bands );
5846 0 : Copy32( hMasaExtRend->hDiracDecBin[0]->ChCrossIm_fx, hDiracDecBin->ChCrossIm_fx, hSpatParamRendCom->num_freq_bands );
5847 0 : Copy( hMasaExtRend->hDiracDecBin[0]->ChCrossRe_e, hDiracDecBin->ChCrossRe_e, hSpatParamRendCom->num_freq_bands );
5848 0 : Copy( hMasaExtRend->hDiracDecBin[0]->ChCrossIm_e, hDiracDecBin->ChCrossIm_e, hSpatParamRendCom->num_freq_bands );
5849 :
5850 0 : ivas_dirac_dec_binaural_formulate_target_covariance_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat_local, subframe,
5851 0 : hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0,
5852 : subFrameTotalEne_fx, subFrameTotalEne_e, IIReneLimiter_fx, NULL );
5853 :
5854 0 : ivas_dirac_dec_binaural_determine_processing_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat_local, subframe,
5855 0 : hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0,
5856 : 0, NULL );
5857 :
5858 :
5859 0 : q_mat = hDiracDecBin->q_processMtx;
5860 0 : move16();
5861 0 : q_mat = s_min( q_mat, hDiracDecBin->q_processMtxPrev );
5862 0 : q_mat = s_min( q_mat, hDiracDecBin->q_processMtxDec );
5863 0 : q_mat = s_min( q_mat, hDiracDecBin->q_processMtxDecPrev );
5864 :
5865 0 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
5866 : {
5867 0 : FOR( slot = 0; slot < BINAURAL_CHANNELS; slot++ )
5868 : {
5869 0 : Scale_sig( hDiracDecBin->processMtxDecRe_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDec ) ); // scaling to q_mat
5870 0 : Scale_sig( hDiracDecBin->processMtxDecIm_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDec ) ); // scaling to q_mat
5871 0 : Scale_sig( hDiracDecBin->processMtxDecRePrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDecPrev ) ); // scaling to q_mat
5872 0 : Scale_sig( hDiracDecBin->processMtxDecImPrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDecPrev ) ); // scaling to q_mat
5873 : }
5874 : }
5875 0 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
5876 : {
5877 0 : FOR( slot = 0; slot < numInChannels; slot++ )
5878 : {
5879 0 : Scale_sig( hDiracDecBin->processMtxRe_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) ); // scaling to q_mat
5880 0 : Scale_sig( hDiracDecBin->processMtxIm_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) ); // scaling to q_mat
5881 0 : Scale_sig( hDiracDecBin->processMtxRePrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); // scaling to q_mat
5882 0 : Scale_sig( hDiracDecBin->processMtxImPrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); // scaling to q_mat
5883 : }
5884 : }
5885 0 : hDiracDecBin->q_processMtx = q_mat;
5886 0 : hDiracDecBin->q_processMtxPrev = q_mat;
5887 0 : hDiracDecBin->q_processMtxDec = q_mat;
5888 0 : hDiracDecBin->q_processMtxDecPrev = q_mat;
5889 0 : move16();
5890 0 : move16();
5891 0 : move16();
5892 0 : move16();
5893 : /* re-use reverb and decorr from main direction for the sides */
5894 0 : ivas_dirac_dec_binaural_process_output_fx( hDiracDecBin, hSpatParamRendCom, hMasaExtRend->cldfbSynRend, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat, tmp_Cldfb_out_re, tmp_Cldfb_out_im,
5895 : reverbRe_fx, reverbIm_fx, decorrRe_fx, decorrIm_fx, &Q_inp_mix, 0 );
5896 :
5897 : /* copy from temporary buffer to the main split rendering buffer */
5898 0 : for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
5899 : {
5900 0 : for ( i = 0; i < CLDFB_SLOTS_PER_SUBFRAME; i++ )
5901 : {
5902 0 : Copy32( tmp_Cldfb_out_re[ch][i], Cldfb_Out_Real[pos_idx * BINAURAL_CHANNELS + ch][subframe * CLDFB_SLOTS_PER_SUBFRAME + i], CLDFB_NO_CHANNELS_MAX );
5903 0 : Copy32( tmp_Cldfb_out_im[ch][i], Cldfb_Out_Imag[pos_idx * BINAURAL_CHANNELS + ch][subframe * CLDFB_SLOTS_PER_SUBFRAME + i], CLDFB_NO_CHANNELS_MAX );
5904 : }
5905 : }
5906 :
5907 0 : hDiracDecBin->hDiffuseDist = NULL;
5908 : }
5909 : }
5910 : }
5911 :
5912 : /* update this counter only after the last rendering of split directions */
5913 :
5914 7200 : hSpatParamRendCom->slots_rendered = add( hSpatParamRendCom->slots_rendered, hSpatParamRendCom->subframe_nbslots[subframe] );
5915 7200 : hSpatParamRendCom->subframes_rendered = add( hSpatParamRendCom->subframes_rendered, 1 );
5916 7200 : move16();
5917 7200 : move16();
5918 :
5919 21600 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
5920 : {
5921 14400 : scale_sig32( output_fx[ch], nBins * hSpatParamRendCom->subframe_nbslots[subframe], sub( Q11, q_out ) ); // Q11
5922 14400 : scale_sig32( hMasaExtRend->cldfbSynRend[ch]->cldfb_state_fx, hMasaExtRend->cldfbSynRend[ch]->cldfb_size, sub( Q11, hMasaExtRend->cldfbSynRend[ch]->Q_cldfb_state ) ); // Q11
5923 14400 : hMasaExtRend->cldfbSynRend[ch]->Q_cldfb_state = Q11;
5924 : }
5925 :
5926 7200 : return;
5927 : }
5928 :
5929 4500 : void ivas_masa_ext_rend_parambin_render_fx(
5930 : MASA_EXT_REND_HANDLE hMasaExtRend, /* i/o: MASA ext rend structure */
5931 : COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i : combined orientation handle */
5932 : Word32 *output_f[], /* i/o: synthesized core-coder transport channels/DirAC output Q11*/
5933 : const Word16 num_subframes, /* i : number of subframes to render */
5934 : const SPLIT_REND_WRAPPER *hSplitRendWrapper, /* i : split rendering orientation data */
5935 : Word32 Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : rendered orientations for split rend. real part of cldfb */
5936 : Word32 Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] /* o : rendered orientations for split rend. imag part of cldfb */
5937 : )
5938 : {
5939 : Word16 subframe;
5940 : SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom;
5941 : Word32 *p_output[BINAURAL_CHANNELS];
5942 : Word16 ch;
5943 :
5944 4500 : hSpatParamRendCom = hMasaExtRend->hSpatParamRendCom;
5945 :
5946 13500 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
5947 : {
5948 9000 : p_output[ch] = output_f[ch];
5949 : }
5950 :
5951 4500 : hSpatParamRendCom->subframes_rendered = hSpatParamRendCom->dirac_read_idx;
5952 4500 : move16();
5953 11700 : FOR( subframe = 0; subframe < num_subframes; subframe++ )
5954 : {
5955 7200 : Word16 n_samples_sf = i_mult( hSpatParamRendCom->slot_size, CLDFB_SLOTS_PER_SUBFRAME );
5956 7200 : hSpatParamRendCom->slots_rendered = 0;
5957 7200 : move16();
5958 :
5959 7200 : ivas_masa_ext_rend_parambin_internal_fx( hMasaExtRend, hCombinedOrientationData, p_output, hSpatParamRendCom->dirac_read_idx, hSplitRendWrapper, Cldfb_Out_Real, Cldfb_Out_Imag );
5960 21600 : FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
5961 : {
5962 14400 : p_output[ch] += n_samples_sf;
5963 : }
5964 :
5965 7200 : ivas_combined_orientation_update_index( hCombinedOrientationData, n_samples_sf );
5966 :
5967 7200 : hSpatParamRendCom->dirac_read_idx = ( add( hSpatParamRendCom->dirac_read_idx, 1 ) ) % hSpatParamRendCom->dirac_md_buffer_length;
5968 7200 : move16();
5969 : }
5970 :
5971 4500 : return;
5972 : }
|