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