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