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