Line data Source code
1 : /*====================================================================================
2 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
3 : ====================================================================================*/
4 :
5 : #define _USE_MATH_DEFINES
6 :
7 : #include <assert.h>
8 : #include <stdint.h>
9 : #include <math.h>
10 : #include "options.h"
11 : #include "basop_util.h"
12 : #include "options.h"
13 : #include "typedef.h"
14 : #include "cnst.h"
15 : #include "prot_fx.h"
16 : #include "stat_com.h"
17 : #include "ivas_prot_fx.h"
18 :
19 : #define CROSSFADE_THRESHOLD ( 32762 ) // close to 1.0f in Q15 such that (x == 1.0f) is true
20 :
21 : /************************************************************************************
22 : * local functions
23 : ************************************************************************************/
24 :
25 : static void CalcMDXT( const TonalMDCTConcealPtr hTonalMDCTConc, const Word16 type, const Word16 *timeSignal, Word32 *mdxtOutput, Word16 *mdxtOutput_e );
26 : static void CalcPowerSpec( const Word32 *mdctSpec, const Word16 mdctSpec_exp, const Word32 *mdstSpec, const Word16 mdstSpec_exp, const Word16 nSamples, const Word16 floorPowerSpectrum, Word32 *powerSpec, Word16 *powerSpec_exp );
27 : static void CalcPowerSpecAndDetectTonalComponents( TonalMDCTConcealPtr const hTonalMDCTConc, Word32 secondLastMDST[], Word16 secondLastMDST_exp, Word32 secondLastMDCT[], Word16 secondLastMDCT_exp, Word32 const pitchLag, Word16 element_mode );
28 : static void FindPhases( TonalMDCTConcealPtr const hTonalMDCTConc, Word32 secondLastMDCT[], Word32 secondLastMDST[], Word16 diff_exp );
29 : static void FindPhaseDifferences( TonalMDCTConcealPtr const hTonalMDCTConc, Word32 powerSpectrum[] );
30 :
31 :
32 : /*******************************************************/
33 : /*-------------- public functions -------------------- */
34 : /*******************************************************/
35 :
36 41 : ivas_error TonalMDCTConceal_Init(
37 : TonalMDCTConcealPtr hTonalMDCTConc,
38 : const Word16 nSamples,
39 : const Word16 nSamplesCore,
40 : const Word16 nScaleFactors,
41 : TCX_CONFIG_HANDLE hTcxCfg /* TCX config */
42 : )
43 : {
44 41 : test();
45 41 : IF( GT_16( nSamples, L_FRAME_MAX ) || GT_16( nScaleFactors, FDNS_NPTS ) )
46 : {
47 0 : assert( nSamples <= L_FRAME_MAX );
48 0 : assert( nScaleFactors <= FDNS_NPTS );
49 0 : return ( IVAS_ERROR( IVAS_ERR_INTERNAL, "TonalMDCT FEC: Number of samples larger than max. block size\n" ) );
50 : }
51 41 : assert( ( hTonalMDCTConc->nScaleFactors == nScaleFactors ) || ( hTonalMDCTConc->nSamples != nSamples ) ); /* If nSamples doesn't change then also nScaleFactors must stay the same */
52 :
53 41 : hTonalMDCTConc->tcx_cfg = hTcxCfg;
54 :
55 41 : hTonalMDCTConc->lastBlockData.spectralData = hTonalMDCTConc->spectralDataBuffers[0];
56 41 : move16();
57 41 : hTonalMDCTConc->secondLastBlockData.spectralData = hTonalMDCTConc->spectralDataBuffers[1];
58 41 : move16();
59 41 : hTonalMDCTConc->secondLastPowerSpectrum = hTonalMDCTConc->secondLastBlockData.spectralData;
60 41 : move16();
61 :
62 41 : hTonalMDCTConc->lastBlockData.scaleFactors = hTonalMDCTConc->scaleFactorsBuffers[0];
63 41 : move16();
64 41 : hTonalMDCTConc->secondLastBlockData.scaleFactors = hTonalMDCTConc->scaleFactorsBuffers[1];
65 41 : move16();
66 41 : hTonalMDCTConc->lastBlockData.scaleFactors_exp = hTonalMDCTConc->scaleFactorsBuffers_exp[0];
67 41 : move16();
68 41 : hTonalMDCTConc->secondLastBlockData.scaleFactors_exp = hTonalMDCTConc->scaleFactorsBuffers_exp[1];
69 41 : move16();
70 :
71 41 : hTonalMDCTConc->lastBlockData.blockIsValid = 0;
72 41 : move16();
73 41 : hTonalMDCTConc->secondLastBlockData.blockIsValid = 0;
74 41 : move16();
75 41 : hTonalMDCTConc->nSamples = 0;
76 41 : move16();
77 41 : hTonalMDCTConc->nScaleFactors = 0;
78 41 : move16();
79 :
80 41 : hTonalMDCTConc->lastBlockData.blockIsConcealed = 0;
81 41 : move16();
82 41 : hTonalMDCTConc->secondLastBlockData.blockIsConcealed = 0;
83 41 : move16();
84 :
85 41 : hTonalMDCTConc->pTCI = (TonalComponentsInfo *) hTonalMDCTConc->timeDataBuffer;
86 41 : move16();
87 :
88 :
89 41 : hTonalMDCTConc->lastPitchLag = L_deposit_l( 0 );
90 :
91 41 : IF( NE_16( hTonalMDCTConc->nSamples, nSamples ) )
92 : {
93 41 : hTonalMDCTConc->secondLastBlockData.blockIsValid = 0;
94 41 : move16();
95 41 : hTonalMDCTConc->lastBlockData.blockIsValid = 0;
96 41 : move16();
97 : }
98 :
99 41 : hTonalMDCTConc->nSamples = nSamples;
100 41 : move16();
101 41 : hTonalMDCTConc->nSamplesCore = nSamplesCore;
102 41 : move16();
103 :
104 41 : hTonalMDCTConc->nScaleFactors = nScaleFactors;
105 41 : move16();
106 : /* Offset the pointer to the end of buffer, so that pTCI is not destroyed when
107 : new time samples are stored in lastPcmOut */
108 41 : move16();
109 41 : move16();
110 : /* just the second half of the second last pcm output is needed */
111 41 : hTonalMDCTConc->secondLastPcmOut = &hTonalMDCTConc->timeDataBuffer[sub( ( 3 * L_FRAME_MAX ) / 2, 3 * ( s_min( L_FRAME_MAX, nSamples ) ) / 2 )];
112 41 : hTonalMDCTConc->lastPcmOut = &hTonalMDCTConc->timeDataBuffer[sub( ( 3 * L_FRAME_MAX ) / 2, s_min( L_FRAME_MAX, nSamples ) )];
113 :
114 : /* If the second last frame was lost, we reuse saved TonalComponentsInfo and don't update pcm buffers */
115 41 : assert( sizeof( *hTonalMDCTConc->pTCI ) <= ( hTonalMDCTConc->lastPcmOut - hTonalMDCTConc->timeDataBuffer ) * sizeof( hTonalMDCTConc->timeDataBuffer[0] ) );
116 :
117 41 : return IVAS_ERR_OK;
118 : }
119 14772 : ivas_error TonalMDCTConceal_Init_ivas_fx(
120 : TonalMDCTConcealPtr hTonalMDCTConc,
121 : const UWord16 nSamples,
122 : const UWord16 nSamplesCore,
123 : const UWord16 nScaleFactors,
124 : TCX_CONFIG_HANDLE hTcxCfg )
125 : {
126 14772 : test();
127 14772 : IF( GT_16( nSamples, L_FRAME_MAX ) || GT_16( nScaleFactors, FDNS_NPTS ) )
128 : {
129 0 : assert( LE_16( nSamples, L_FRAME_MAX ) );
130 0 : assert( LE_16( nScaleFactors, FDNS_NPTS ) );
131 0 : return ( IVAS_ERROR( IVAS_ERR_INTERNAL, "TonalMDCT FEC: Number of samples larger than max. block size\n" ) );
132 : }
133 14772 : assert( EQ_16( hTonalMDCTConc->nScaleFactors, nScaleFactors ) || NE_16( hTonalMDCTConc->nSamples, nSamples ) ); /* If nSamples doesn't change then also nScaleFactors must stay the same */
134 :
135 14772 : hTonalMDCTConc->tcx_cfg = hTcxCfg;
136 14772 : hTonalMDCTConc->lastBlockData.spectralData = hTonalMDCTConc->spectralDataBuffers[0];
137 14772 : set16_fx( hTonalMDCTConc->lastBlockData.spectralData, 0, L_FRAME_MAX );
138 14772 : move16();
139 14772 : hTonalMDCTConc->secondLastBlockData.spectralData = hTonalMDCTConc->spectralDataBuffers[1];
140 14772 : set16_fx( hTonalMDCTConc->secondLastBlockData.spectralData, 0, L_FRAME_MAX );
141 14772 : move16();
142 14772 : hTonalMDCTConc->secondLastPowerSpectrum = hTonalMDCTConc->secondLastBlockData.spectralData;
143 14772 : move16();
144 14772 : hTonalMDCTConc->secondLastPowerSpectrum_exp = hTonalMDCTConc->secondLastBlockData.spectralData_exp;
145 14772 : move16();
146 14772 : hTonalMDCTConc->lastBlockData.scaleFactors = hTonalMDCTConc->scaleFactorsBuffers[0];
147 14772 : set16_fx( hTonalMDCTConc->lastBlockData.scaleFactors, 0, FDNS_NPTS );
148 14772 : move16();
149 14772 : hTonalMDCTConc->secondLastBlockData.scaleFactors = hTonalMDCTConc->scaleFactorsBuffers[1];
150 14772 : set16_fx( hTonalMDCTConc->secondLastBlockData.scaleFactors, 0, FDNS_NPTS );
151 14772 : move16();
152 14772 : hTonalMDCTConc->lastBlockData.scaleFactors_exp = hTonalMDCTConc->scaleFactorsBuffers_exp[0];
153 14772 : move16();
154 14772 : hTonalMDCTConc->secondLastBlockData.scaleFactors_exp = hTonalMDCTConc->scaleFactorsBuffers_exp[1];
155 14772 : move16();
156 :
157 14772 : hTonalMDCTConc->lastBlockData.blockIsValid = 0;
158 14772 : move16();
159 14772 : hTonalMDCTConc->secondLastBlockData.blockIsValid = 0;
160 14772 : move16();
161 14772 : hTonalMDCTConc->nSamples = 0;
162 14772 : move16();
163 14772 : hTonalMDCTConc->nScaleFactors = 0;
164 14772 : move16();
165 :
166 14772 : hTonalMDCTConc->lastBlockData.blockIsConcealed = 0;
167 14772 : move16();
168 14772 : hTonalMDCTConc->secondLastBlockData.blockIsConcealed = 0;
169 14772 : move16();
170 14772 : hTonalMDCTConc->pTCI = (TonalComponentsInfo *) hTonalMDCTConc->timeDataBuffer;
171 :
172 14772 : move16();
173 14772 : hTonalMDCTConc->lastPitchLag = L_deposit_l( 0 );
174 :
175 14772 : IF( NE_16( hTonalMDCTConc->nSamples, nSamples ) )
176 : {
177 14772 : hTonalMDCTConc->secondLastBlockData.blockIsValid = 0;
178 14772 : move16();
179 14772 : hTonalMDCTConc->lastBlockData.blockIsValid = 0;
180 14772 : move16();
181 : }
182 14772 : hTonalMDCTConc->nSamples = nSamples;
183 14772 : move16();
184 14772 : hTonalMDCTConc->nSamplesCore = nSamplesCore;
185 14772 : move16();
186 14772 : hTonalMDCTConc->nScaleFactors = nScaleFactors;
187 14772 : move16();
188 :
189 14772 : set32_fx( hTonalMDCTConc->scaleFactorsBackground_fx, 0, FDNS_NPTS );
190 14772 : hTonalMDCTConc->scf_fadeout = 16384 /*1.000000 Q14*/;
191 14772 : PsychoacousticParameters_Init_fx( INT_FS_16k, L_FRAME16k, 64, 1, 1, &hTonalMDCTConc->psychParamsTCX20 );
192 14772 : PsychoacousticParameters_Init_fx( INT_FS_16k, L_FRAME16k / 2, 64, 0, 1, &hTonalMDCTConc->psychParamsTCX10 );
193 14772 : hTonalMDCTConc->psychParams = NULL;
194 :
195 14772 : hTonalMDCTConc->last_block_nrg = 0;
196 14772 : move16();
197 14772 : hTonalMDCTConc->last_block_nrg_exp = 0;
198 14772 : move16();
199 14772 : hTonalMDCTConc->curr_noise_nrg = 0;
200 14772 : move16();
201 14772 : hTonalMDCTConc->curr_noise_nrg_exp = 0;
202 14772 : move16();
203 14772 : hTonalMDCTConc->faded_signal_nrg = 0;
204 14772 : move16();
205 14772 : hTonalMDCTConc->faded_signal_nrg_exp = 0;
206 14772 : move16();
207 :
208 : /* Offset the pointer to the end of buffer, so that pTCI is not destroyed when
209 : new time samples are stored in lastPcmOut */
210 14772 : move16();
211 14772 : move16();
212 : /* just the second half of the second last pcm output is needed */
213 :
214 14772 : set16_fx( hTonalMDCTConc->timeDataBuffer, 0, ( 3 * L_FRAME_MAX ) / 2 );
215 14772 : hTonalMDCTConc->secondLastPcmOut = &hTonalMDCTConc->timeDataBuffer[( 3 * L_FRAME_MAX ) / 2 - ( 3 * min( L_FRAME_MAX, nSamples ) / 2 )];
216 14772 : hTonalMDCTConc->lastPcmOut = &hTonalMDCTConc->timeDataBuffer[( 3 * L_FRAME_MAX ) / 2 - min( L_FRAME_MAX, nSamples )];
217 : /* If the second last frame was lost, we reuse saved TonalComponentsInfo and don't update pcm buffers */
218 14772 : assert( sizeof( *hTonalMDCTConc->pTCI ) <= ( hTonalMDCTConc->lastPcmOut - hTonalMDCTConc->timeDataBuffer ) * sizeof( hTonalMDCTConc->timeDataBuffer[0] ) );
219 :
220 14772 : return IVAS_ERR_OK;
221 : }
222 646 : void TonalMDCTConceal_SaveFreqSignal(
223 : TonalMDCTConcealPtr hTonalMDCTConc,
224 : const Word32 *mdctSpectrum, // Q31-mdctSpectrum_exp
225 : const Word16 mdctSpectrum_exp,
226 : Word16 nNewSamples, // Q0
227 : Word16 nNewSamplesCore, // Q0
228 : const Word16 *scaleFactors, // Q31-scaleFactors_exp
229 : const Word16 *scaleFactors_exp,
230 : const Word16 gain_tcx_exp )
231 : {
232 : Word16 *temp;
233 : Word16 nOldSamples, tmp_exp, s, i, max_exp;
234 :
235 :
236 646 : assert( nNewSamples > 0 && nNewSamples <= 2 * L_FRAME_MAX );
237 :
238 : /* Avoid overwriting hTonalMDCTConc->secondLastPowerSpectrum stored in spectralData,
239 : because it is needed if the second last and the current frame are lost
240 : and concealed using the Tonal MDCT PLC */
241 646 : test();
242 646 : IF( !hTonalMDCTConc->lastBlockData.tonalConcealmentActive || NE_16( hTonalMDCTConc->lastBlockData.nSamples, nNewSamples ) )
243 : {
244 646 : IF( LE_16( nNewSamples, L_FRAME_MAX ) )
245 : {
246 : /* Shift the buffers */
247 624 : temp = hTonalMDCTConc->secondLastBlockData.spectralData; /* Save the pointer */
248 624 : move16();
249 624 : hTonalMDCTConc->secondLastBlockData.spectralData = hTonalMDCTConc->lastBlockData.spectralData;
250 624 : move16();
251 624 : hTonalMDCTConc->lastBlockData.spectralData = temp;
252 624 : move16();
253 :
254 624 : tmp_exp = hTonalMDCTConc->secondLastBlockData.spectralData_exp; /* Save the pointer */
255 624 : move16();
256 624 : hTonalMDCTConc->secondLastBlockData.spectralData_exp = hTonalMDCTConc->lastBlockData.spectralData_exp;
257 624 : move16();
258 624 : hTonalMDCTConc->lastBlockData.spectralData_exp = tmp_exp;
259 624 : move16();
260 :
261 624 : tmp_exp = hTonalMDCTConc->secondLastBlockData.gain_tcx_exp; /* Save the pointer */
262 624 : move16();
263 624 : hTonalMDCTConc->secondLastBlockData.gain_tcx_exp = hTonalMDCTConc->lastBlockData.gain_tcx_exp;
264 624 : move16();
265 624 : hTonalMDCTConc->lastBlockData.gain_tcx_exp = tmp_exp;
266 624 : move16();
267 :
268 624 : tmp_exp = hTonalMDCTConc->secondLastBlockData.scaleFactors_max_e; /* Save the pointer */
269 624 : move16();
270 624 : hTonalMDCTConc->secondLastBlockData.scaleFactors_max_e = hTonalMDCTConc->lastBlockData.scaleFactors_max_e;
271 624 : move16();
272 624 : hTonalMDCTConc->lastBlockData.scaleFactors_max_e = tmp_exp;
273 624 : move16();
274 :
275 624 : temp = hTonalMDCTConc->secondLastBlockData.scaleFactors;
276 624 : move16();
277 624 : hTonalMDCTConc->secondLastBlockData.scaleFactors = hTonalMDCTConc->lastBlockData.scaleFactors;
278 624 : move16();
279 624 : hTonalMDCTConc->lastBlockData.scaleFactors = temp;
280 624 : move16();
281 :
282 624 : temp = hTonalMDCTConc->secondLastBlockData.scaleFactors_exp;
283 624 : move16();
284 624 : hTonalMDCTConc->secondLastBlockData.scaleFactors_exp = hTonalMDCTConc->lastBlockData.scaleFactors_exp;
285 624 : move16();
286 624 : hTonalMDCTConc->lastBlockData.scaleFactors_exp = temp;
287 624 : move16();
288 : }
289 : ELSE
290 : {
291 22 : hTonalMDCTConc->lastBlockData.spectralData = hTonalMDCTConc->spectralDataBuffers[0];
292 22 : move16();
293 22 : hTonalMDCTConc->secondLastBlockData.spectralData = hTonalMDCTConc->spectralDataBuffers[1];
294 22 : move16();
295 22 : hTonalMDCTConc->lastBlockData.scaleFactors = hTonalMDCTConc->scaleFactorsBuffers[0];
296 22 : move16();
297 22 : hTonalMDCTConc->secondLastBlockData.scaleFactors = hTonalMDCTConc->scaleFactorsBuffers[1];
298 22 : move16();
299 22 : hTonalMDCTConc->lastBlockData.scaleFactors_exp = hTonalMDCTConc->scaleFactorsBuffers_exp[0];
300 22 : move16();
301 22 : hTonalMDCTConc->secondLastBlockData.scaleFactors_exp = hTonalMDCTConc->scaleFactorsBuffers_exp[1];
302 22 : move16();
303 : }
304 :
305 646 : nOldSamples = hTonalMDCTConc->lastBlockData.nSamples;
306 646 : move16();
307 646 : hTonalMDCTConc->lastBlockData.nSamples = nNewSamples;
308 646 : move16();
309 646 : hTonalMDCTConc->secondLastBlockData.nSamples = nOldSamples;
310 646 : move16();
311 :
312 646 : nOldSamples = hTonalMDCTConc->lastBlockData.nSamplesCore;
313 646 : move16();
314 646 : hTonalMDCTConc->lastBlockData.nSamplesCore = nNewSamplesCore;
315 646 : move16();
316 646 : hTonalMDCTConc->secondLastBlockData.nSamplesCore = nOldSamples;
317 646 : move16();
318 : }
319 :
320 646 : test();
321 646 : IF( ( nNewSamples > 0 ) && ( LE_16( nNewSamples, 2 * L_FRAME_MAX ) ) )
322 : {
323 : /* Store new data */
324 646 : s = getScaleFactor32( mdctSpectrum, nNewSamples );
325 :
326 : /*Copy(scaleFactors_exp, hTonalMDCTConc->lastBlockData.scaleFactors_exp, hTonalMDCTConc->nScaleFactors);*/
327 646 : max_exp = 0;
328 41990 : FOR( i = 0; i < hTonalMDCTConc->nScaleFactors; i++ )
329 : {
330 41344 : hTonalMDCTConc->lastBlockData.scaleFactors_exp[i] = scaleFactors_exp[i];
331 41344 : move16();
332 41344 : max_exp = s_max( max_exp, scaleFactors_exp[i] );
333 : }
334 :
335 : /*s = sub(s, max_exp);*/
336 646 : hTonalMDCTConc->lastBlockData.scaleFactors_max_e = max_exp;
337 :
338 540646 : FOR( i = 0; i < nNewSamples; i++ )
339 : {
340 540000 : hTonalMDCTConc->lastBlockData.spectralData[i] = extract_h( L_shl( mdctSpectrum[i], s ) ); // Q31-(mdctSpectrum_exp-s)
341 540000 : move16();
342 : }
343 646 : hTonalMDCTConc->lastBlockData.spectralData_exp = sub( mdctSpectrum_exp, s );
344 646 : move16();
345 646 : hTonalMDCTConc->lastBlockData.gain_tcx_exp = gain_tcx_exp;
346 :
347 646 : Copy( scaleFactors, hTonalMDCTConc->lastBlockData.scaleFactors, hTonalMDCTConc->nScaleFactors );
348 : }
349 646 : return;
350 : }
351 :
352 823867 : void TonalMDCTConceal_SaveFreqSignal_ivas_fx(
353 : TonalMDCTConcealPtr hTonalMDCTConc,
354 : const Word32 *mdctSpectrum, // Q31-mdctSpectrum_exp
355 : const Word16 mdctSpectrum_exp, // Q0
356 : const Word16 nNewSamples, // Q0
357 : const Word16 nNewSamplesCore, // Q0
358 : const Word16 *scaleFactors, // Q15 - *scaleFactors_exp
359 : const Word16 *scaleFactors_exp, // Q0
360 : const Word16 gain_tcx_exp, // Q0
361 : const Word16 infoIGFStartLine ) // Q0
362 : {
363 : Word16 *temp;
364 : Word16 nOldSamples, temp_exp, s, i, max_exp;
365 :
366 823867 : assert( nNewSamples > 0 && nNewSamples <= 2 * L_FRAME_MAX );
367 :
368 : /* Avoid overwriting hTonalMDCTConc->secondLastPowerSpectrum stored in spectralData,
369 : because it is needed if the second last and the current frame are lost
370 : and concealed using the Tonal MDCT PLC */
371 823867 : test();
372 823867 : IF( !hTonalMDCTConc->lastBlockData.tonalConcealmentActive || NE_16( hTonalMDCTConc->lastBlockData.nSamples, nNewSamples ) )
373 : {
374 823511 : IF( LE_16( nNewSamples, L_FRAME_MAX ) )
375 : {
376 : /* Shift the buffers */
377 817407 : temp = hTonalMDCTConc->secondLastBlockData.spectralData; /* Save the pointer */
378 817407 : move16();
379 817407 : hTonalMDCTConc->secondLastBlockData.spectralData = hTonalMDCTConc->lastBlockData.spectralData;
380 817407 : move16();
381 817407 : hTonalMDCTConc->lastBlockData.spectralData = temp;
382 817407 : move16();
383 :
384 817407 : temp_exp = hTonalMDCTConc->secondLastBlockData.spectralData_exp;
385 817407 : move16();
386 817407 : hTonalMDCTConc->secondLastBlockData.spectralData_exp = hTonalMDCTConc->lastBlockData.spectralData_exp;
387 817407 : move16();
388 817407 : hTonalMDCTConc->lastBlockData.spectralData_exp = temp_exp;
389 817407 : move16();
390 :
391 817407 : temp_exp = hTonalMDCTConc->secondLastBlockData.gain_tcx_exp; /* Save the pointer */
392 817407 : move16();
393 817407 : hTonalMDCTConc->secondLastBlockData.gain_tcx_exp = hTonalMDCTConc->lastBlockData.gain_tcx_exp;
394 817407 : move16();
395 817407 : hTonalMDCTConc->lastBlockData.gain_tcx_exp = temp_exp;
396 817407 : move16();
397 :
398 817407 : temp_exp = hTonalMDCTConc->secondLastBlockData.scaleFactors_max_e; /* Save the pointer */
399 817407 : move16();
400 817407 : hTonalMDCTConc->secondLastBlockData.scaleFactors_max_e = hTonalMDCTConc->lastBlockData.scaleFactors_max_e;
401 817407 : move16();
402 817407 : hTonalMDCTConc->lastBlockData.scaleFactors_max_e = temp_exp;
403 817407 : move16();
404 :
405 817407 : temp = hTonalMDCTConc->secondLastBlockData.scaleFactors;
406 817407 : move16();
407 817407 : hTonalMDCTConc->secondLastBlockData.scaleFactors = hTonalMDCTConc->lastBlockData.scaleFactors;
408 817407 : move16();
409 817407 : hTonalMDCTConc->lastBlockData.scaleFactors = temp;
410 817407 : move16();
411 :
412 817407 : temp = hTonalMDCTConc->secondLastBlockData.scaleFactors_exp;
413 817407 : move16();
414 817407 : hTonalMDCTConc->secondLastBlockData.scaleFactors_exp = hTonalMDCTConc->lastBlockData.scaleFactors_exp;
415 817407 : move16();
416 817407 : hTonalMDCTConc->lastBlockData.scaleFactors_exp = temp;
417 817407 : move16();
418 : }
419 : ELSE
420 : {
421 : /* Order the buffers so that even transition frame can fit in if written into the first buffer */
422 6104 : hTonalMDCTConc->lastBlockData.spectralData = hTonalMDCTConc->spectralDataBuffers[0];
423 6104 : move16();
424 6104 : hTonalMDCTConc->secondLastBlockData.spectralData = hTonalMDCTConc->spectralDataBuffers[1];
425 6104 : move16();
426 6104 : hTonalMDCTConc->lastBlockData.scaleFactors = hTonalMDCTConc->scaleFactorsBuffers[0];
427 6104 : move16();
428 6104 : hTonalMDCTConc->secondLastBlockData.scaleFactors = hTonalMDCTConc->scaleFactorsBuffers[1];
429 6104 : move16();
430 6104 : hTonalMDCTConc->lastBlockData.scaleFactors_exp = hTonalMDCTConc->scaleFactorsBuffers_exp[0];
431 6104 : move16();
432 6104 : hTonalMDCTConc->secondLastBlockData.scaleFactors_exp = hTonalMDCTConc->scaleFactorsBuffers_exp[1];
433 6104 : move16();
434 : }
435 823511 : nOldSamples = hTonalMDCTConc->lastBlockData.nSamples;
436 823511 : move16();
437 823511 : hTonalMDCTConc->lastBlockData.nSamples = nNewSamples;
438 823511 : move16();
439 823511 : hTonalMDCTConc->secondLastBlockData.nSamples = nOldSamples;
440 823511 : move16();
441 823511 : nOldSamples = (Word16) hTonalMDCTConc->lastBlockData.nSamplesCore;
442 823511 : move16();
443 823511 : hTonalMDCTConc->lastBlockData.nSamplesCore = (UWord16) nNewSamplesCore;
444 823511 : move16();
445 823511 : hTonalMDCTConc->secondLastBlockData.nSamplesCore = (UWord16) nOldSamples;
446 823511 : move16();
447 : }
448 :
449 823867 : test();
450 823867 : IF( ( nNewSamples > 0 ) && ( LE_16( nNewSamples, 2 * L_FRAME_MAX ) ) )
451 : {
452 : /* Store new data */
453 823867 : Word64 W_tmp = 0;
454 823867 : move64();
455 394418097 : FOR( i = 0; i < infoIGFStartLine; i++ )
456 : {
457 393594230 : W_tmp = W_mac_32_16( W_tmp, Mpy_32_32( mdctSpectrum[i], mdctSpectrum[i] ), 1 ); // exp: mdctSpectrum_exp + mdctSpectrum_exp - 1
458 : }
459 823867 : s = W_norm( W_tmp );
460 823867 : hTonalMDCTConc->last_block_nrg = W_extract_h( W_shl( W_tmp, s ) ); // exp:add( sub( shl( mdctSpectrum_exp, 1 ), s ), 31 )
461 823867 : move32();
462 823867 : hTonalMDCTConc->last_block_nrg_exp = add( sub( shl( mdctSpectrum_exp, 1 ), s ), 31 );
463 823867 : move16();
464 :
465 : /* Store new data */
466 823867 : s = getScaleFactor32( mdctSpectrum, nNewSamples );
467 :
468 823867 : max_exp = 0;
469 823867 : move16();
470 53551355 : FOR( i = 0; i < hTonalMDCTConc->nScaleFactors; i++ )
471 : {
472 52727488 : hTonalMDCTConc->lastBlockData.scaleFactors_exp[i] = scaleFactors_exp[i];
473 52727488 : move16();
474 52727488 : max_exp = s_max( max_exp, scaleFactors_exp[i] );
475 : }
476 :
477 : /*s = sub(s, max_exp);*/
478 823867 : hTonalMDCTConc->lastBlockData.scaleFactors_max_e = max_exp;
479 823867 : move16();
480 :
481 685996827 : FOR( i = 0; i < nNewSamples; i++ )
482 : {
483 685172960 : Word16 tmp = 0;
484 685172960 : if ( mdctSpectrum[i] != 0 )
485 : {
486 490786411 : tmp = 1;
487 490786411 : move16();
488 : }
489 685172960 : hTonalMDCTConc->lastBlockData.spectralData[i] = extract_h( L_shl( mdctSpectrum[i], s ) ); // 31 - mdctSpectrum_exp +s -16 = 15-(mdctSpectrum_exp -s)
490 685172960 : move16();
491 :
492 685172960 : test();
493 685172960 : if ( hTonalMDCTConc->lastBlockData.spectralData[i] == 0 && EQ_16( tmp, 1 ) )
494 : {
495 5306081 : hTonalMDCTConc->lastBlockData.spectralData[i] = 1;
496 5306081 : move16();
497 : }
498 : }
499 823867 : hTonalMDCTConc->lastBlockData.spectralData_exp = sub( mdctSpectrum_exp, s );
500 823867 : move16();
501 :
502 823867 : hTonalMDCTConc->lastBlockData.gain_tcx_exp = gain_tcx_exp;
503 823867 : move16();
504 823867 : Copy( scaleFactors, hTonalMDCTConc->lastBlockData.scaleFactors, hTonalMDCTConc->nScaleFactors );
505 : }
506 :
507 823867 : return;
508 : }
509 :
510 :
511 912662 : void TonalMDCTConceal_UpdateState(
512 : TonalMDCTConcealPtr hTonalMDCTConc,
513 : Word16 nNewSamples, // Q0
514 : Word32 pitchLag, // Qx
515 : Word16 badBlock, // Q0
516 : Word8 tonalConcealmentActive )
517 : {
518 : Word8 newBlockIsValid;
519 :
520 912662 : assert( !( !badBlock && tonalConcealmentActive ) );
521 :
522 912662 : IF( badBlock )
523 : {
524 13232 : newBlockIsValid = (Word8) hTonalMDCTConc->lastBlockData.blockIsValid;
525 13232 : move16();
526 : }
527 : ELSE
528 : {
529 899430 : newBlockIsValid = 0;
530 899430 : move16();
531 899430 : test();
532 899430 : if ( ( LE_16( nNewSamples, 2 * L_FRAME_MAX ) ) && ( nNewSamples > 0 ) )
533 : {
534 894174 : newBlockIsValid = 1;
535 894174 : move16();
536 : }
537 : }
538 :
539 912662 : /* Shift old state */ move16();
540 912662 : move16();
541 912662 : move16();
542 912662 : hTonalMDCTConc->secondLastBlockData.blockIsConcealed = hTonalMDCTConc->lastBlockData.blockIsConcealed;
543 912662 : hTonalMDCTConc->secondLastBlockData.blockIsValid = hTonalMDCTConc->lastBlockData.blockIsValid;
544 912662 : hTonalMDCTConc->secondLastBlockData.tonalConcealmentActive = hTonalMDCTConc->lastBlockData.tonalConcealmentActive;
545 :
546 912662 : /* Store new state */ move16();
547 912662 : move16();
548 912662 : move16();
549 912662 : hTonalMDCTConc->lastBlockData.blockIsConcealed = badBlock;
550 912662 : hTonalMDCTConc->lastBlockData.blockIsValid = newBlockIsValid;
551 912662 : hTonalMDCTConc->lastBlockData.tonalConcealmentActive = tonalConcealmentActive;
552 :
553 912662 : hTonalMDCTConc->lastPitchLag = pitchLag;
554 912662 : move32();
555 :
556 912662 : return;
557 : }
558 :
559 :
560 : /* o: currenc phase [-pi;pi] 2Q13 */
561 1497 : static void FindPhases(
562 : TonalMDCTConcealPtr const hTonalMDCTConc, /* i: pointer to internal structure */
563 : Word32 secondLastMDCT[], /* i: MDST spectrum data Qx +31 -diff_exp */
564 : Word32 secondLastMDST[], /* i: MDCT spectrum data Qx */
565 : Word16 diff_exp ) /* i: exp_MDST - exp_MDCT */
566 : {
567 : Word16 i;
568 : Word16 l;
569 : Word16 *pCurrentPhase;
570 :
571 :
572 1497 : pCurrentPhase = hTonalMDCTConc->pTCI->phase_currentFramePredicted;
573 : /* for each index/index group */
574 4665 : FOR( i = 0; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
575 : {
576 25293 : FOR( l = hTonalMDCTConc->pTCI->lowerIndex[i]; l <= hTonalMDCTConc->pTCI->upperIndex[i]; l++ )
577 : {
578 : /* in contrast to the float code, the parameter secondLastMDST[l]
579 : needs not to be negated - due to a different implementation of
580 : the MDST */
581 22125 : *pCurrentPhase++ = BASOP_util_atan2( secondLastMDST[l], secondLastMDCT[l], diff_exp ); // Q13
582 22125 : move16();
583 : }
584 : }
585 :
586 1497 : return;
587 : }
588 :
589 : #define BANDWIDTH 7.0f
590 : #define G 789516047l /*1.0/(2*1.36) Q31*/
591 : #define MAXRATIO 22938 /*44.8f Q9*/ /* Maximum ratio |ODFT[k-1]|/|ODFT[k+1]| is 16.5 dB, that is maximum ratio (for fractional = 0) is (cos(PI/bandwidth)/cos(3PI/bandwidth))^1.36 */
592 : #define MM 1934815907 /* FL2WORD32(cos(EVS_PI/BANDWIDTH)); */
593 : #define SS 29166 /* FL2WORD16(cos((3*EVS_PI)/BANDWIDTH)*4); Q17*/
594 : #define N 931758243 /* FL2WORD32(sin(EVS_PI/BANDWIDTH)); */
595 : #define J 31946 /* FL2WORD16(sin((3*EVS_PI)/BANDWIDTH)); */
596 :
597 : /* o: Phase difference [-pi;pi] 2Q13*/
598 1497 : static void FindPhaseDifferences(
599 : TonalMDCTConcealPtr const hTonalMDCTConc, /* i: Pointer to internal structure */
600 : Word32 powerSpectrum[] ) /* i: Power spectrum data Qx */
601 : {
602 : Word16 i, k;
603 : Word16 *phaseDiff;
604 : Word16 fractional, sf, sfn, sfd;
605 : Word16 divi, s, j;
606 : Word32 a, Q, L_tmp, m, n;
607 :
608 1497 : s = SS;
609 1497 : move16();
610 1497 : j = J;
611 1497 : move16();
612 :
613 1497 : phaseDiff = hTonalMDCTConc->pTCI->phaseDiff;
614 :
615 4665 : FOR( i = 0; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
616 : {
617 3168 : m = MM;
618 3168 : move16();
619 3168 : n = N;
620 3168 : move16();
621 :
622 3168 : k = hTonalMDCTConc->pTCI->indexOfTonalPeak[i];
623 3168 : move16();
624 :
625 3168 : IF( GE_32( Mpy_32_16_1( powerSpectrum[k - 1], 512 /*1.0f Q9*/ ), Mpy_32_16_1( powerSpectrum[k + 1], MAXRATIO ) ) )
626 : {
627 14 : phaseDiff[i] = 0; /*(float)tan(0.0f*EVS_PI/bandwidth);*/
628 14 : move16();
629 14 : if ( s_and( k, 1 ) != 0 )
630 : {
631 6 : phaseDiff[i] = -12868 /*-EVS_PI 3Q12*/;
632 6 : move16();
633 : }
634 : }
635 : ELSE
636 : {
637 3154 : IF( GE_32( Mpy_32_16_1( powerSpectrum[k + 1], 512 /*1.0f Q9*/ ), Mpy_32_16_1( powerSpectrum[k - 1], MAXRATIO ) ) )
638 : {
639 29 : phaseDiff[i] = 12868 /*EVS_PI 3Q12*/; /*(float)tan(2.0f*PI/bandwidth);*/
640 29 : move16();
641 29 : if ( s_and( k, 1 ) != 0 )
642 : {
643 12 : phaseDiff[i] = 0 /*0 Q13*/; /*2Q13*/
644 12 : move16();
645 : }
646 : }
647 : ELSE
648 : {
649 : /*Q = (float)pow(odft_left/odft_right, G);
650 : a = (m - Q * s) / (n + Q * j);
651 : phaseDiff[i] = (float)atan(a) * (bandwidth/2.0f);*/
652 : /*max divi=44.8 & sf=6*/
653 3125 : divi = BASOP_Util_Divide3232_uu_1616_Scale( powerSpectrum[k - 1], powerSpectrum[k + 1], &sf );
654 3125 : Q = BASOP_Util_fPow( L_deposit_h( divi ), sf, G, 0, &sf ); // Q31-sf
655 3125 : L_tmp = Mpy_32_16_1( Q, s );
656 3125 : sfn = sub( sf, 2 );
657 :
658 3125 : if ( sfn > 0 )
659 : {
660 117 : m = L_shr( m, sfn );
661 : }
662 3125 : IF( sfn < 0 )
663 : {
664 2320 : L_tmp = L_shl( L_tmp, sfn );
665 2320 : sfn = 0;
666 2320 : move16();
667 : }
668 :
669 3125 : a = L_sub( m, L_tmp ); /*sf*/
670 :
671 3125 : L_tmp = Mpy_32_16_1( Q, j );
672 3125 : IF( sf >= 0 )
673 : {
674 2970 : L_tmp = L_shr( L_tmp, 1 );
675 2970 : sfd = add( sf, 1 );
676 2970 : n = L_shr( n, sfd );
677 : }
678 : ELSE
679 : {
680 155 : sfd = 0;
681 155 : move16();
682 155 : L_tmp = L_shl( L_tmp, sf );
683 : }
684 :
685 3125 : L_tmp = L_add( n, L_tmp );
686 3125 : fractional = BASOP_util_atan2( a, L_tmp, sub( sfn, sfd ) ); /*2Q13*/
687 3125 : L_tmp = L_mult( fractional, 28672 /*BANDWIDTH/2.0f Q13*/ ); /*2Q13*2Q13=4Q27*/
688 :
689 : /* fractional is in the range 0..+pi */
690 : /* we need to stay in the range -2pi..+2pi */
691 3125 : if ( EQ_16( s_and( k, 3 ), 1 ) )
692 : {
693 688 : L_tmp = L_add( L_tmp, 421657440l /*+1*EVS_PI Q27*/ );
694 : }
695 3125 : if ( EQ_16( s_and( k, 3 ), 2 ) )
696 : {
697 770 : L_tmp = L_sub( L_tmp, 843314880l /*+2*EVS_PI=-2*EVS_PI Q27*/ );
698 : }
699 3125 : if ( EQ_16( s_and( k, 3 ), 3 ) )
700 : {
701 1091 : L_tmp = L_sub( L_tmp, 421657440l /*+3*EVS_PI=-1*EVS_PI Q27*/ );
702 : }
703 3125 : phaseDiff[i] = round_fx( L_shl( L_tmp, 1 ) ); /*3Q12*/
704 3125 : move16();
705 : }
706 : }
707 : }
708 1497 : }
709 :
710 1497 : static void ivas_CalcPowerSpecAndDetectTonalComponents_fx(
711 : TonalMDCTConcealPtr const hTonalMDCTConc,
712 : Word32 secondLastMDST[], // Q31 - secondLastMDST_exp
713 : Word16 secondLastMDST_exp,
714 : Word32 secondLastMDCT[], // Q31 - secondLastMDCT_exp
715 : Word16 secondLastMDCT_exp,
716 : Word32 const pitchLag, /*15Q16*/
717 : const PsychoacousticParameters *psychParamsCurrent,
718 : Word16 element_mode )
719 : {
720 : Word16 nSamples;
721 : Word16 i;
722 : Word16 floorPowerSpectrum; /* Minimum significant value of a spectral line in the power spectrum */
723 : Word32 powerSpectrum[L_FRAME_MAX];
724 : Word16 invScaleFactors[FDNS_NPTS];
725 : Word16 invScaleFactors_exp[FDNS_NPTS];
726 : Word16 powerSpectrum_exp, tmp_exp, old_exp;
727 : #ifndef ISSUE_1866_replace_overflow_libdec
728 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
729 : Flag Overflow = 0;
730 : move32();
731 : #endif
732 : #endif
733 :
734 : Word16 nBands;
735 : Word32 invScaleFactors_fx[FDNS_NPTS];
736 : Word16 old_power_spectrum_q, power_spectrum_q;
737 :
738 1497 : set32_fx( powerSpectrum, 0, L_FRAME_MAX );
739 :
740 1497 : nSamples = hTonalMDCTConc->nNonZeroSamples;
741 1497 : move16();
742 :
743 : /* It is taken into account that the MDCT is not normalized. */
744 1497 : floorPowerSpectrum /*Q0*/ = extract_l( Mpy_32_32( L_mult0( hTonalMDCTConc->nSamples, hTonalMDCTConc->nSamples ), 5368709 ) ); /*1/400 = 5368709 Q31*/
745 1497 : powerSpectrum_exp = 0;
746 1497 : move16();
747 :
748 1497 : CalcPowerSpec( secondLastMDCT,
749 : secondLastMDCT_exp,
750 : secondLastMDST,
751 : secondLastMDST_exp,
752 : nSamples,
753 : floorPowerSpectrum,
754 : powerSpectrum,
755 : &powerSpectrum_exp );
756 :
757 : /* This setting to minimal level is required because the power spectrum is used in the threshold adaptation using the pitch up to hTonalMDCTConc->nSamples. */
758 1497 : set32_fx( powerSpectrum + nSamples, floorPowerSpectrum, sub( hTonalMDCTConc->nSamples, nSamples ) );
759 : /* this setting to zero is needed since the FDNS needs to be called
760 : with hTonalMDCTConc->nSamplesCore; it relevant only for nb; it has no effect
761 : to the output, but memory checker may complain otherwise due to the
762 : usage of uninitialized values */
763 1497 : IF( GT_16( hTonalMDCTConc->nSamplesCore, hTonalMDCTConc->nSamples ) )
764 : {
765 61 : set32_fx( powerSpectrum + hTonalMDCTConc->nSamples, 0, sub( hTonalMDCTConc->nSamplesCore, hTonalMDCTConc->nSamples ) );
766 : }
767 :
768 1497 : ivas_DetectTonalComponents_fx( (Word16 *) hTonalMDCTConc->pTCI->indexOfTonalPeak,
769 1497 : (Word16 *) hTonalMDCTConc->pTCI->lowerIndex,
770 1497 : (Word16 *) hTonalMDCTConc->pTCI->upperIndex,
771 1497 : (Word16 *) &hTonalMDCTConc->pTCI->numIndexes,
772 : hTonalMDCTConc->lastPitchLag,
773 : pitchLag,
774 1497 : hTonalMDCTConc->lastBlockData.spectralData,
775 1497 : hTonalMDCTConc->lastBlockData.spectralData_exp,
776 1497 : hTonalMDCTConc->lastBlockData.scaleFactors,
777 1497 : hTonalMDCTConc->lastBlockData.scaleFactors_exp,
778 1497 : hTonalMDCTConc->lastBlockData.scaleFactors_max_e,
779 : powerSpectrum,
780 : powerSpectrum_exp,
781 : nSamples,
782 1497 : hTonalMDCTConc->nSamplesCore,
783 : floorPowerSpectrum, psychParamsCurrent, element_mode );
784 1497 : FindPhases( hTonalMDCTConc, secondLastMDCT, secondLastMDST, sub( secondLastMDST_exp, secondLastMDCT_exp ) );
785 :
786 1497 : FindPhaseDifferences( hTonalMDCTConc, powerSpectrum );
787 :
788 1497 : IF( hTonalMDCTConc->pTCI->numIndexes > 0 )
789 : {
790 590 : hTonalMDCTConc->secondLastPowerSpectrum = hTonalMDCTConc->secondLastBlockData.spectralData;
791 :
792 : /*sqrtFLOAT(powerSpectrum, powerSpectrum, nSamples);*/
793 590 : old_exp = powerSpectrum_exp;
794 590 : move16();
795 590 : powerSpectrum_exp = mult_r( sub( powerSpectrum_exp, 2 ), ( 1 << 14 ) ); /*remove 2 bits of headroom from CalcPowerSpec*/
796 329385 : FOR( i = 0; i < nSamples; i++ )
797 : {
798 328795 : tmp_exp = old_exp;
799 328795 : move16();
800 328795 : powerSpectrum[i] = Sqrt32( powerSpectrum[i], &tmp_exp );
801 328795 : move32();
802 328795 : powerSpectrum[i] = L_shr( powerSpectrum[i], sub( powerSpectrum_exp, tmp_exp ) ); // Q31-(powerSpectrum_exp-tmp_exp)
803 328795 : move32();
804 : }
805 :
806 38350 : FOR( i = 0; i < hTonalMDCTConc->nScaleFactors; i++ )
807 : {
808 37760 : invScaleFactors_exp[i] = hTonalMDCTConc->secondLastBlockData.scaleFactors_exp[i];
809 37760 : move16();
810 37760 : invScaleFactors[i] = Inv16( hTonalMDCTConc->secondLastBlockData.scaleFactors[i], &invScaleFactors_exp[i] ); // Q31-invScaleFactors_exp[i]
811 37760 : move16();
812 : }
813 :
814 590 : power_spectrum_q = sub( 31, powerSpectrum_exp );
815 590 : old_power_spectrum_q = power_spectrum_q;
816 590 : move16();
817 590 : Word16 length = 0;
818 590 : move16();
819 : /* here mdct_shaping() is intentionally used rather then mdct_shaping_16() */
820 590 : IF( psychParamsCurrent == NULL )
821 : {
822 226 : nBands = FDNS_NPTS;
823 226 : move16();
824 226 : mdct_shaping( powerSpectrum, hTonalMDCTConc->nSamplesCore, invScaleFactors, invScaleFactors_exp );
825 : }
826 : ELSE
827 : {
828 23660 : FOR( i = 0; i < FDNS_NPTS; i++ )
829 : {
830 23296 : invScaleFactors_fx[i] = L_shl( invScaleFactors[i], add( 1, invScaleFactors_exp[i] ) ); // Q16
831 23296 : move32();
832 : }
833 364 : sns_shape_spectrum_fx( powerSpectrum, &power_spectrum_q, psychParamsCurrent, invScaleFactors_fx, 16, hTonalMDCTConc->nSamplesCore, &length );
834 364 : power_spectrum_q = add( power_spectrum_q, 1 );
835 364 : nBands = psychParamsCurrent->nBands;
836 364 : move16();
837 : }
838 590 : IF( LT_16( old_power_spectrum_q, power_spectrum_q ) )
839 : {
840 361 : Scale_sig32( powerSpectrum, length, sub( old_power_spectrum_q, power_spectrum_q ) ); // Q(old_power_spectrum_q-power_spectrum_q)
841 : }
842 : ELSE
843 : {
844 229 : Scale_sig32( powerSpectrum + length, sub( nSamples, length ), sub( power_spectrum_q, old_power_spectrum_q ) ); // Q(power_spectrum_q - old_power_spectrum_q)
845 229 : powerSpectrum_exp = sub( 31, power_spectrum_q );
846 : }
847 590 : Scale_sig32( powerSpectrum, nSamples, -3 ); /*Adding guard bits*/ // Q(31 - powerSpectrum_exp )-3
848 590 : powerSpectrum_exp = add( powerSpectrum_exp, 3 );
849 63578 : FOR( i = hTonalMDCTConc->nSamplesCore; i < nSamples; i++ )
850 : {
851 62988 : powerSpectrum[i] = L_shl_sat( Mpy_32_16_1( powerSpectrum[i], invScaleFactors[nBands - 1] ), invScaleFactors_exp[nBands - 1] ); // Q(31 - powerSpectrum_exp)
852 62988 : move32();
853 : }
854 :
855 590 : Word16 shift = Find_Max_Norm32( powerSpectrum, nSamples );
856 590 : scale_sig32( powerSpectrum, nSamples, shift );
857 590 : powerSpectrum_exp = sub( powerSpectrum_exp, shift );
858 :
859 : /* 16 bits are now enough for storing the power spectrum */
860 329385 : FOR( i = 0; i < nSamples; i++ )
861 : {
862 : #ifdef ISSUE_1866_replace_overflow_libdec
863 328795 : hTonalMDCTConc->secondLastPowerSpectrum[i] = round_fx_sat( powerSpectrum[i] ); // Q31 - powerSpectrum_exp
864 : #else
865 : hTonalMDCTConc->secondLastPowerSpectrum[i] = round_fx_o( powerSpectrum[i], &Overflow ); // Q31 - powerSpectrum_exp
866 : #endif
867 328795 : move32();
868 : }
869 :
870 590 : hTonalMDCTConc->secondLastPowerSpectrum_exp = powerSpectrum_exp;
871 590 : move16();
872 : }
873 1497 : }
874 :
875 0 : static void CalcPowerSpecAndDetectTonalComponents(
876 : TonalMDCTConcealPtr const hTonalMDCTConc,
877 : Word32 secondLastMDST[], // Q31-secondLastMDST_exp
878 : Word16 secondLastMDST_exp,
879 : Word32 secondLastMDCT[], // Q31-secondLastMDCT_exp
880 : Word16 secondLastMDCT_exp,
881 : Word32 const pitchLag, /*15Q16*/
882 : Word16 element_mode )
883 : {
884 : Word16 nSamples;
885 : Word16 i;
886 : Word16 floorPowerSpectrum; /* Minimum significant value of a spectral line in the power spectrum */
887 : Word32 powerSpectrum[L_FRAME_MAX];
888 : Word16 invScaleFactors[FDNS_NPTS];
889 : Word16 invScaleFactors_exp[FDNS_NPTS];
890 : Word16 powerSpectrum_exp, tmp_exp, old_exp;
891 : #ifndef ISSUE_1866_replace_overflow_libdec
892 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
893 : Flag Overflow = 0;
894 : move32();
895 : #endif
896 : #endif
897 :
898 :
899 0 : nSamples = hTonalMDCTConc->nNonZeroSamples;
900 0 : move16();
901 :
902 : /* It is taken into account that the MDCT is not normalized. */
903 0 : floorPowerSpectrum /*Q0*/ = extract_l( Mpy_32_16_1( L_mult0( hTonalMDCTConc->nSamples, hTonalMDCTConc->nSamples ), 82 ) ); /*1/400 = 82 Q15*/
904 0 : powerSpectrum_exp = 0;
905 0 : move16();
906 :
907 0 : CalcPowerSpec( secondLastMDCT,
908 : secondLastMDCT_exp,
909 : secondLastMDST,
910 : secondLastMDST_exp,
911 : nSamples,
912 : floorPowerSpectrum,
913 : powerSpectrum,
914 : &powerSpectrum_exp );
915 :
916 : /* This setting to minimal level is required because the power spectrum is used in the threshold adaptation using the pitch up to hTonalMDCTConc->nSamples. */
917 0 : set32_fx( powerSpectrum + nSamples, floorPowerSpectrum, sub( hTonalMDCTConc->nSamples, nSamples ) );
918 : /* this setting to zero is needed since the FDNS needs to be called
919 : with hTonalMDCTConc->nSamplesCore; it relevant only for nb; it has no effect
920 : to the output, but memory checker may complain otherwise due to the
921 : usage of uninitialized values */
922 0 : IF( GT_16( hTonalMDCTConc->nSamplesCore, hTonalMDCTConc->nSamples ) )
923 : {
924 0 : set32_fx( powerSpectrum + hTonalMDCTConc->nSamples, 0, sub( hTonalMDCTConc->nSamplesCore, hTonalMDCTConc->nSamples ) );
925 : }
926 :
927 0 : DetectTonalComponents( (Word16 *) hTonalMDCTConc->pTCI->indexOfTonalPeak,
928 0 : (Word16 *) hTonalMDCTConc->pTCI->lowerIndex,
929 0 : (Word16 *) hTonalMDCTConc->pTCI->upperIndex,
930 0 : (Word16 *) &hTonalMDCTConc->pTCI->numIndexes,
931 : hTonalMDCTConc->lastPitchLag,
932 : pitchLag,
933 0 : hTonalMDCTConc->lastBlockData.spectralData,
934 0 : add( hTonalMDCTConc->lastBlockData.spectralData_exp, hTonalMDCTConc->lastBlockData.gain_tcx_exp ),
935 0 : hTonalMDCTConc->lastBlockData.scaleFactors,
936 0 : hTonalMDCTConc->lastBlockData.scaleFactors_exp,
937 0 : hTonalMDCTConc->lastBlockData.scaleFactors_max_e,
938 : powerSpectrum,
939 : nSamples,
940 0 : hTonalMDCTConc->nSamplesCore,
941 : floorPowerSpectrum, element_mode );
942 0 : FindPhases( hTonalMDCTConc, secondLastMDCT, secondLastMDST, sub( secondLastMDST_exp, secondLastMDCT_exp ) );
943 :
944 0 : FindPhaseDifferences( hTonalMDCTConc, powerSpectrum );
945 :
946 0 : IF( hTonalMDCTConc->pTCI->numIndexes > 0 )
947 : {
948 :
949 0 : hTonalMDCTConc->secondLastPowerSpectrum = hTonalMDCTConc->secondLastBlockData.spectralData;
950 :
951 : /*sqrtFLOAT(powerSpectrum, powerSpectrum, nSamples);*/
952 0 : old_exp = powerSpectrum_exp;
953 0 : move16();
954 0 : powerSpectrum_exp = mult_r( sub( powerSpectrum_exp, 2 ), 1 << 14 ); /*remove 2 bits of headroom from CalcPowerSpec*/
955 0 : FOR( i = 0; i < nSamples; i++ )
956 : {
957 0 : tmp_exp = old_exp;
958 0 : move16();
959 0 : powerSpectrum[i] = Sqrt32( powerSpectrum[i], &tmp_exp ); // Q31- tmp_exp
960 0 : powerSpectrum[i] = L_shr( powerSpectrum[i], sub( powerSpectrum_exp, tmp_exp ) ); // Q31- tmp_exp
961 0 : move32();
962 : }
963 :
964 0 : FOR( i = 0; i < hTonalMDCTConc->nScaleFactors; i++ )
965 : {
966 0 : move16();
967 0 : move16();
968 0 : invScaleFactors_exp[i] = hTonalMDCTConc->secondLastBlockData.scaleFactors_exp[i];
969 0 : invScaleFactors[i] = Inv16( hTonalMDCTConc->secondLastBlockData.scaleFactors[i], &invScaleFactors_exp[i] ); // Q31 - invScaleFactors_exp[i]
970 : }
971 :
972 :
973 : /* here mdct_shaping() is intentionally used rather then mdct_shaping_16() */
974 : {
975 0 : mdct_shaping( powerSpectrum, hTonalMDCTConc->nSamplesCore, invScaleFactors, invScaleFactors_exp );
976 : }
977 0 : FOR( i = hTonalMDCTConc->nSamplesCore; i < nSamples; i++ )
978 : {
979 0 : powerSpectrum[i] = L_shl_sat( Mpy_32_16_1( powerSpectrum[i], invScaleFactors[FDNS_NPTS - 1] ), invScaleFactors_exp[FDNS_NPTS - 1] ); // powerSpectrum_exp+ 2*invScaleFactors_exp -15
980 0 : move32();
981 : }
982 :
983 : /* 16 bits are now enough for storing the power spectrum */
984 0 : FOR( i = 0; i < nSamples; i++ )
985 : {
986 : #ifdef ISSUE_1866_replace_overflow_libdec
987 0 : hTonalMDCTConc->secondLastPowerSpectrum[i] = round_fx_sat( powerSpectrum[i] ); // Q31-powerSpectrum_exp
988 : #else
989 : hTonalMDCTConc->secondLastPowerSpectrum[i] = round_fx_o( powerSpectrum[i], &Overflow ); // Q31-powerSpectrum_exp
990 : #endif
991 0 : move32();
992 : }
993 :
994 0 : powerSpectrum_exp = sub( powerSpectrum_exp, hTonalMDCTConc->secondLastBlockData.gain_tcx_exp );
995 0 : hTonalMDCTConc->secondLastPowerSpectrum_exp = powerSpectrum_exp;
996 0 : move16();
997 : }
998 0 : }
999 :
1000 :
1001 2994 : static void CalcMDXT(
1002 : const TonalMDCTConcealPtr hTonalMDCTConc,
1003 : const Word16 type,
1004 : const Word16 *timeSignal, // Qx
1005 : Word32 *mdxtOutput, // Q31-mdxtOutput_e
1006 : Word16 *mdxtOutput_e )
1007 : {
1008 : Word16 windowedTimeSignal[L_FRAME_PLUS + 2 * L_MDCT_OVLP_MAX];
1009 : Word16 left_overlap, right_overlap, L_frame;
1010 :
1011 2994 : L_frame = hTonalMDCTConc->nSamples;
1012 2994 : move16();
1013 :
1014 2994 : WindowSignal( hTonalMDCTConc->tcx_cfg, hTonalMDCTConc->tcx_cfg->tcx_offsetFB, FULL_OVERLAP,
1015 : FULL_OVERLAP, &left_overlap, &right_overlap, timeSignal, &L_frame, windowedTimeSignal, 1, 1 );
1016 :
1017 2994 : IF( type == 0 )
1018 : {
1019 1497 : TCX_MDST( windowedTimeSignal, mdxtOutput, mdxtOutput_e, left_overlap,
1020 1497 : sub( L_frame, shr( add( left_overlap, right_overlap ), 1 ) ), right_overlap, EVS_MONO );
1021 : }
1022 : ELSE
1023 : {
1024 1497 : TCX_MDCT( windowedTimeSignal, mdxtOutput, mdxtOutput_e, left_overlap,
1025 1497 : sub( L_frame, shr( add( left_overlap, right_overlap ), 1 ) ), right_overlap, EVS_MONO );
1026 : }
1027 2994 : }
1028 :
1029 0 : void TonalMDCTConceal_Detect(
1030 : const TonalMDCTConcealPtr hTonalMDCTConc,
1031 : const Word32 pitchLag, /*15Q16*/
1032 : Word16 *numIndices,
1033 : Word16 element_mode )
1034 : {
1035 : Word32 secondLastMDST[L_FRAME_MAX];
1036 : Word32 secondLastMDCT[L_FRAME_MAX];
1037 : Word16 secondLastMDCT_exp;
1038 0 : Word32 *powerSpectrum = secondLastMDST;
1039 : Word16 i, powerSpectrum_exp, secondLastMDST_exp, s;
1040 : Word16 nSamples;
1041 :
1042 :
1043 0 : nSamples = hTonalMDCTConc->nSamples;
1044 0 : move16();
1045 0 : secondLastMDST_exp = 16; /*time signal Q-1*/
1046 0 : move16();
1047 0 : secondLastMDCT_exp = 16; /*time signal Q-1*/
1048 0 : move16();
1049 0 : test();
1050 0 : test();
1051 0 : test();
1052 0 : test();
1053 0 : test();
1054 0 : IF( hTonalMDCTConc->lastBlockData.blockIsValid && hTonalMDCTConc->secondLastBlockData.blockIsValid && ( EQ_16( hTonalMDCTConc->lastBlockData.nSamples, nSamples ) ) && ( EQ_16( hTonalMDCTConc->secondLastBlockData.nSamples, nSamples ) ) && ( !hTonalMDCTConc->secondLastBlockData.blockIsConcealed || hTonalMDCTConc->secondLastBlockData.tonalConcealmentActive || ( pitchLag != 0 ) ) )
1055 : {
1056 : /* Safety if the second last frame was concealed and tonal concealment was inactive */
1057 :
1058 0 : IF( hTonalMDCTConc->lastBlockData.blockIsConcealed == 0 )
1059 : {
1060 0 : IF( hTonalMDCTConc->secondLastBlockData.tonalConcealmentActive == 0 )
1061 : {
1062 0 : CalcMDXT( hTonalMDCTConc, 0, hTonalMDCTConc->secondLastPcmOut, secondLastMDST, &secondLastMDST_exp );
1063 0 : CalcMDXT( hTonalMDCTConc, 1, hTonalMDCTConc->secondLastPcmOut, secondLastMDCT, &secondLastMDCT_exp );
1064 0 : hTonalMDCTConc->nNonZeroSamples = 0;
1065 0 : move16();
1066 0 : FOR( i = 0; i < hTonalMDCTConc->nSamples; i++ )
1067 : {
1068 0 : if ( hTonalMDCTConc->secondLastBlockData.spectralData[i] != 0 )
1069 : {
1070 0 : hTonalMDCTConc->nNonZeroSamples = i;
1071 0 : move16();
1072 : }
1073 : }
1074 :
1075 : /* 23 is the maximum length of the MA filter in getEnvelope */
1076 0 : hTonalMDCTConc->nNonZeroSamples = s_min( hTonalMDCTConc->nSamples, add( hTonalMDCTConc->nNonZeroSamples, 23 ) );
1077 0 : move16();
1078 0 : nSamples = hTonalMDCTConc->nNonZeroSamples;
1079 0 : move16();
1080 :
1081 0 : s = getScaleFactor32( secondLastMDST, nSamples );
1082 :
1083 0 : FOR( i = 0; i < nSamples; i++ )
1084 : {
1085 0 : secondLastMDST[i] = L_shl( secondLastMDST[i], s );
1086 0 : move32();
1087 : }
1088 0 : secondLastMDST_exp = sub( secondLastMDST_exp, s );
1089 0 : move16();
1090 0 : s = getScaleFactor32( secondLastMDCT, nSamples );
1091 :
1092 0 : FOR( i = 0; i < nSamples; i++ )
1093 : {
1094 0 : secondLastMDCT[i] = L_shl( secondLastMDCT[i], s );
1095 0 : move32();
1096 : }
1097 0 : secondLastMDCT_exp = sub( secondLastMDCT_exp, s );
1098 0 : move16();
1099 0 : CalcPowerSpecAndDetectTonalComponents( hTonalMDCTConc, secondLastMDST, secondLastMDST_exp, secondLastMDCT, secondLastMDCT_exp, pitchLag, element_mode );
1100 : }
1101 : ELSE
1102 : {
1103 : /* If the second last frame was also lost, it is expected that pastTimeSignal could hold a bit different signal (e.g. including fade-out) from the one stored in TonalMDCTConceal_SaveTimeSignal. */
1104 : /* That is why we reuse the already stored information about the concealed spectrum in the second last frame */
1105 : {
1106 0 : nSamples = hTonalMDCTConc->nNonZeroSamples;
1107 0 : move16();
1108 0 : mdct_shaping_16( hTonalMDCTConc->secondLastPowerSpectrum, hTonalMDCTConc->nSamplesCore, nSamples,
1109 0 : hTonalMDCTConc->secondLastBlockData.scaleFactors, hTonalMDCTConc->secondLastBlockData.scaleFactors_exp,
1110 0 : hTonalMDCTConc->secondLastBlockData.scaleFactors_max_e, powerSpectrum );
1111 : }
1112 0 : powerSpectrum_exp = getScaleFactor32( powerSpectrum, nSamples );
1113 0 : powerSpectrum_exp = sub( powerSpectrum_exp, 3 ); /*extra 3 bits of headroom for MA filter in getEnvelope*/
1114 :
1115 : /* multFLOAT(powerSpectrum, powerSpectrum, powerSpectrum, nSamples); */
1116 0 : FOR( i = 0; i < nSamples; i++ )
1117 : {
1118 0 : Word32 const t = L_shl( powerSpectrum[i], powerSpectrum_exp ); // Q(31-secondLastMDST_exp+powerSpectrum_exp)
1119 0 : powerSpectrum[i] = Mpy_32_32( t, t ); // Q2*(31-secondLastMDST_exp+powerSpectrum_exp) -31
1120 0 : move32();
1121 : }
1122 :
1123 0 : RefineTonalComponents( (Word16 *) hTonalMDCTConc->pTCI->indexOfTonalPeak,
1124 0 : (Word16 *) hTonalMDCTConc->pTCI->lowerIndex,
1125 0 : (Word16 *) hTonalMDCTConc->pTCI->upperIndex,
1126 0 : hTonalMDCTConc->pTCI->phaseDiff,
1127 0 : hTonalMDCTConc->pTCI->phase_currentFramePredicted,
1128 0 : (Word16 *) &hTonalMDCTConc->pTCI->numIndexes,
1129 : hTonalMDCTConc->lastPitchLag,
1130 : pitchLag,
1131 0 : hTonalMDCTConc->lastBlockData.spectralData,
1132 0 : add( hTonalMDCTConc->lastBlockData.spectralData_exp, hTonalMDCTConc->lastBlockData.gain_tcx_exp ),
1133 0 : hTonalMDCTConc->lastBlockData.scaleFactors,
1134 0 : hTonalMDCTConc->lastBlockData.scaleFactors_exp,
1135 0 : hTonalMDCTConc->lastBlockData.scaleFactors_max_e,
1136 : powerSpectrum,
1137 : nSamples,
1138 0 : hTonalMDCTConc->nSamplesCore,
1139 0 : extract_l( Mpy_32_16_1( L_mult0( hTonalMDCTConc->nSamples, hTonalMDCTConc->nSamples ), 82 ) ), element_mode ); /* floorPowerSpectrum */
1140 : }
1141 : }
1142 : }
1143 : ELSE
1144 : {
1145 0 : hTonalMDCTConc->pTCI->numIndexes = 0;
1146 0 : move16();
1147 : }
1148 :
1149 0 : *numIndices = hTonalMDCTConc->pTCI->numIndexes;
1150 0 : move16();
1151 :
1152 :
1153 0 : return;
1154 : }
1155 :
1156 1673 : void TonalMDCTConceal_Detect_ivas_fx(
1157 : const TonalMDCTConcealPtr hTonalMDCTConc,
1158 : const Word32 pitchLag, /*15Q16*/
1159 : Word16 *numIndices,
1160 : const PsychoacousticParameters *psychParamsCurrent,
1161 : Word16 element_mode )
1162 : {
1163 : Word32 secondLastMDST[L_FRAME_MAX];
1164 1673 : set32_fx( secondLastMDST, 0, L_FRAME_MAX );
1165 : Word32 secondLastMDCT[L_FRAME_MAX];
1166 : Word16 secondLastMDCT_exp;
1167 1673 : Word32 *powerSpectrum = secondLastMDST;
1168 : Word16 i, powerSpectrum_exp, secondLastMDST_exp, s;
1169 : Word16 nSamples;
1170 : // Word16 nBands;
1171 : Word32 sns_int_scf_fx[FDNS_NPTS];
1172 1673 : set32_fx( sns_int_scf_fx, 0, FDNS_NPTS );
1173 :
1174 1673 : nSamples = hTonalMDCTConc->nSamples;
1175 1673 : move16();
1176 1673 : secondLastMDST_exp = sub( 16, hTonalMDCTConc->q_lastPcmOut ); /*time signal Q-1 - hTonalMDCTConc->q_lastPcmOut*/
1177 1673 : move16();
1178 1673 : secondLastMDCT_exp = sub( 16, hTonalMDCTConc->q_lastPcmOut ); /*time signal Q-1 - hTonalMDCTConc->q_lastPcmOut*/
1179 1673 : move16();
1180 1673 : test();
1181 1673 : test();
1182 1673 : test();
1183 1673 : test();
1184 1673 : test();
1185 1673 : IF( hTonalMDCTConc->lastBlockData.blockIsValid && hTonalMDCTConc->secondLastBlockData.blockIsValid && ( EQ_16( hTonalMDCTConc->lastBlockData.nSamples, nSamples ) ) && ( EQ_16( hTonalMDCTConc->secondLastBlockData.nSamples, nSamples ) ) && ( !hTonalMDCTConc->secondLastBlockData.blockIsConcealed || hTonalMDCTConc->secondLastBlockData.tonalConcealmentActive || ( pitchLag != 0 ) ) )
1186 : {
1187 : /* Safety if the second last frame was concealed and tonal concealment was inactive */
1188 :
1189 1497 : IF( hTonalMDCTConc->lastBlockData.blockIsConcealed == 0 )
1190 : {
1191 1497 : IF( hTonalMDCTConc->secondLastBlockData.tonalConcealmentActive == 0 )
1192 : {
1193 1497 : CalcMDXT( hTonalMDCTConc, 0, hTonalMDCTConc->secondLastPcmOut, secondLastMDST, &secondLastMDST_exp );
1194 1497 : CalcMDXT( hTonalMDCTConc, 1, hTonalMDCTConc->secondLastPcmOut, secondLastMDCT, &secondLastMDCT_exp );
1195 1497 : hTonalMDCTConc->nNonZeroSamples = 0;
1196 1497 : move16();
1197 1171417 : FOR( i = 0; i < hTonalMDCTConc->nSamples; i++ )
1198 : {
1199 1169920 : if ( hTonalMDCTConc->secondLastBlockData.spectralData[i] != 0 )
1200 : {
1201 709797 : hTonalMDCTConc->nNonZeroSamples = i;
1202 709797 : move16();
1203 : }
1204 : }
1205 :
1206 : /* 23 is the maximum length of the MA filter in getEnvelope */
1207 1497 : hTonalMDCTConc->nNonZeroSamples = s_min( hTonalMDCTConc->nSamples, add( hTonalMDCTConc->nNonZeroSamples, 23 ) );
1208 1497 : move16();
1209 1497 : nSamples = hTonalMDCTConc->nNonZeroSamples;
1210 1497 : move16();
1211 :
1212 1497 : s = sub( getScaleFactor32( secondLastMDST, nSamples ), 1 );
1213 :
1214 781158 : FOR( i = 0; i < nSamples; i++ )
1215 : {
1216 779661 : secondLastMDST[i] = L_shl( secondLastMDST[i], s );
1217 779661 : move32();
1218 : }
1219 1497 : secondLastMDST_exp = sub( secondLastMDST_exp, s );
1220 1497 : move16();
1221 1497 : s = sub( getScaleFactor32( secondLastMDCT, nSamples ), 1 );
1222 :
1223 781158 : FOR( i = 0; i < nSamples; i++ )
1224 : {
1225 779661 : secondLastMDCT[i] = L_shl( secondLastMDCT[i], s );
1226 779661 : move32();
1227 : }
1228 1497 : secondLastMDCT_exp = sub( secondLastMDCT_exp, s );
1229 1497 : move16();
1230 1497 : ivas_CalcPowerSpecAndDetectTonalComponents_fx( hTonalMDCTConc, secondLastMDST, secondLastMDST_exp, secondLastMDCT, secondLastMDCT_exp, pitchLag, psychParamsCurrent, element_mode );
1231 : }
1232 : ELSE
1233 : {
1234 : /* If the second last frame was also lost, it is expected that pastTimeSignal could hold a bit different signal (e.g. including fade-out) from the one stored in TonalMDCTConceal_SaveTimeSignal. */
1235 : /* That is why we reuse the already stored information about the concealed spectrum in the second last frame */
1236 0 : Word16 temp_power_spectrum_q = 0;
1237 0 : nSamples = hTonalMDCTConc->nNonZeroSamples;
1238 0 : move16();
1239 0 : Copy_Scale_sig_16_32_DEPREC( hTonalMDCTConc->secondLastPowerSpectrum, powerSpectrum, nSamples, Q15 );
1240 0 : temp_power_spectrum_q = add( Q15, sub( 15, hTonalMDCTConc->secondLastPowerSpectrum_exp ) );
1241 0 : IF( psychParamsCurrent == NULL )
1242 : {
1243 0 : mdct_shaping_16( hTonalMDCTConc->secondLastPowerSpectrum, hTonalMDCTConc->nSamplesCore, nSamples,
1244 0 : hTonalMDCTConc->secondLastBlockData.scaleFactors, hTonalMDCTConc->secondLastBlockData.scaleFactors_exp,
1245 0 : hTonalMDCTConc->secondLastBlockData.scaleFactors_max_e, powerSpectrum );
1246 :
1247 0 : powerSpectrum_exp = getScaleFactor32( powerSpectrum, nSamples );
1248 0 : powerSpectrum_exp = sub( powerSpectrum_exp, 3 ); /*extra 3 bits of headroom for MA filter in getEnvelope*/
1249 :
1250 : /* multFLOAT(powerSpectrum, powerSpectrum, powerSpectrum, nSamples); */
1251 0 : FOR( i = 0; i < nSamples; i++ )
1252 : {
1253 0 : Word32 const t = L_shl( powerSpectrum[i], powerSpectrum_exp ); // Q(31-secondLastMDST_exp+powerSpectrum_exp)
1254 0 : powerSpectrum[i] = Mpy_32_32( t, t ); // Q(31-secondLastMDST_exp+powerSpectrum_exp)
1255 0 : move32();
1256 : }
1257 0 : powerSpectrum_exp = 0;
1258 0 : move16();
1259 : }
1260 : ELSE
1261 : {
1262 0 : FOR( i = 0; i < FDNS_NPTS; i++ )
1263 : {
1264 0 : sns_int_scf_fx[i] = L_shl( hTonalMDCTConc->secondLastBlockData.scaleFactors[i], add( 1, hTonalMDCTConc->secondLastBlockData.scaleFactors_exp[i] ) ); // Q16
1265 0 : move32();
1266 : }
1267 0 : sns_shape_spectrum_fx( powerSpectrum, &temp_power_spectrum_q, psychParamsCurrent, sns_int_scf_fx, 16, hTonalMDCTConc->nSamplesCore, NULL );
1268 0 : powerSpectrum_exp = sub( 31, temp_power_spectrum_q );
1269 :
1270 0 : FOR( i = 0; i < nSamples; i++ )
1271 : {
1272 0 : Word32 const t = L_shl( powerSpectrum[i], -3 ); // Q31 - powerSpectrum_exp -3
1273 0 : powerSpectrum[i] = Mpy_32_32( t, t ); // 2*(Q31 - powerSpectrum_exp -3)-31
1274 0 : move32();
1275 : }
1276 0 : powerSpectrum_exp = sub( 31, sub( shl( sub( Q31 - 3, powerSpectrum_exp ), 1 ), 31 ) );
1277 : }
1278 :
1279 0 : ivas_RefineTonalComponents_fx( (Word16 *) hTonalMDCTConc->pTCI->indexOfTonalPeak,
1280 0 : (Word16 *) hTonalMDCTConc->pTCI->lowerIndex,
1281 0 : (Word16 *) hTonalMDCTConc->pTCI->upperIndex,
1282 0 : hTonalMDCTConc->pTCI->phaseDiff,
1283 0 : hTonalMDCTConc->pTCI->phase_currentFramePredicted,
1284 0 : (Word16 *) &hTonalMDCTConc->pTCI->numIndexes,
1285 : hTonalMDCTConc->lastPitchLag,
1286 : pitchLag,
1287 0 : hTonalMDCTConc->lastBlockData.spectralData,
1288 0 : add( hTonalMDCTConc->lastBlockData.spectralData_exp, hTonalMDCTConc->lastBlockData.gain_tcx_exp ),
1289 0 : hTonalMDCTConc->lastBlockData.scaleFactors,
1290 0 : hTonalMDCTConc->lastBlockData.scaleFactors_exp,
1291 0 : hTonalMDCTConc->lastBlockData.scaleFactors_max_e,
1292 : powerSpectrum,
1293 : powerSpectrum_exp,
1294 : nSamples,
1295 0 : hTonalMDCTConc->nSamplesCore,
1296 0 : extract_l( Mpy_32_16_1( L_mult0( hTonalMDCTConc->nSamples, hTonalMDCTConc->nSamples ), 82 ) ), element_mode, psychParamsCurrent ); /* floorPowerSpectrum */
1297 : }
1298 : }
1299 : }
1300 : ELSE
1301 : {
1302 176 : hTonalMDCTConc->pTCI->numIndexes = 0;
1303 176 : move16();
1304 : }
1305 :
1306 1673 : *numIndices = hTonalMDCTConc->pTCI->numIndexes;
1307 1673 : move16();
1308 :
1309 :
1310 1673 : return;
1311 : }
1312 :
1313 8733 : void TonalMDCTConceal_InsertNoise_ivas_fx(
1314 : const TonalMDCTConcealPtr hTonalMDCTConc, /*IN */
1315 : Word32 *mdctSpectrum, // Q31-mdctSpectrum_exp
1316 : Word16 *mdctSpectrum_exp,
1317 : const Word16 tonalConcealmentActive,
1318 : Word16 *pSeed, /*IN/OUT*/
1319 : const Word16 tiltCompFactor, // Q15
1320 : const Word16 crossfadeGain_const, // Q15
1321 : const Word32 concealment_noise[L_FRAME48k], // Q31-concealment_noise_e
1322 : const Word16 concealment_noise_e,
1323 : const Word32 cngLevelBackgroundTrace_bfi, // Q31-cngLevelBackgroundTrace_bfi_e
1324 : const Word16 cngLevelBackgroundTrace_bfi_e,
1325 : const Word16 crossOverFreq ) // Q0
1326 : {
1327 : Word16 i, l, ld, fac;
1328 : Word16 rnd;
1329 :
1330 : Word16 tmp, g, tilt, exp_last, exp_noise, tiltFactor, crossfadeGain, e_crossfadeGain;
1331 : Word32 L_tmp, L_tmp1, L_tmp2, nrgNoiseInLastFrame, nrgWhiteNoise;
1332 : Word16 inv_exp, inv_samples, exp;
1333 : Word32 last_block_nrg_correct;
1334 : Word16 last_block_nrg_correct_e;
1335 : Word32 max_concealment_value;
1336 : Word16 max_spectral_value;
1337 : Word64 sum1, sum2;
1338 : Word16 num16, den16, exp1, exp2;
1339 : Word16 shift1, shift2;
1340 :
1341 8733 : crossfadeGain = crossfadeGain_const;
1342 8733 : move16();
1343 8733 : e_crossfadeGain = 0;
1344 8733 : move16();
1345 8733 : push_wmops( "InsertNoise" );
1346 :
1347 8733 : g = sub( MAX16B, crossfadeGain );
1348 :
1349 8733 : IF( !hTonalMDCTConc->lastBlockData.blockIsConcealed )
1350 : {
1351 4816 : rnd = 1977;
1352 4816 : move16();
1353 : }
1354 : ELSE
1355 : {
1356 3917 : rnd = *pSeed;
1357 3917 : move16();
1358 : }
1359 :
1360 : /* based on what is done in tcx_noise_filling() */
1361 : /* always initialize these to avoid compiler warnings */
1362 8733 : hTonalMDCTConc->faded_signal_nrg = L_deposit_h( 0 );
1363 8733 : move32();
1364 :
1365 8733 : L_tmp = 805306368l /*0.375f Q31*/;
1366 8733 : move32();
1367 8733 : inv_exp = 15;
1368 8733 : move16();
1369 8733 : inv_samples = Inv16( hTonalMDCTConc->lastBlockData.nSamples, &inv_exp ); // Q31-inv_exp
1370 8733 : tiltFactor = round_fx( BASOP_Util_fPow( L_max( L_tmp, L_deposit_h( tiltCompFactor ) ), 0, L_deposit_h( inv_samples ), inv_exp, &exp ) ); // Q15 - exp
1371 : BASOP_SATURATE_WARNING_OFF_EVS /*next op may result in 32768*/
1372 8733 : tiltFactor = shl_sat( tiltFactor, exp ); // Q15
1373 : BASOP_SATURATE_WARNING_ON_EVS
1374 8733 : tilt = MAX16B;
1375 8733 : move16();
1376 8733 : nrgNoiseInLastFrame = L_deposit_h( 0 );
1377 8733 : nrgWhiteNoise = L_deposit_h( 0 );
1378 8733 : last_block_nrg_correct = L_deposit_h( 0 );
1379 8733 : last_block_nrg_correct_e = 0;
1380 8733 : move16();
1381 8733 : exp_last = exp_noise = 0;
1382 8733 : move16();
1383 8733 : move16();
1384 :
1385 8733 : IF( !hTonalMDCTConc->lastBlockData.blockIsValid )
1386 : {
1387 : /* may just become active if the very first frame is lost */
1388 0 : set32_fx( mdctSpectrum, 0, hTonalMDCTConc->nSamples );
1389 : }
1390 8733 : ELSE IF( concealment_noise != NULL )
1391 : {
1392 3108 : IF( !tonalConcealmentActive )
1393 : {
1394 : /* if fadeout has not started yet, only apply sign scrambling */
1395 3013 : IF( GE_16( crossfadeGain_const, CROSSFADE_THRESHOLD ) )
1396 : {
1397 577620 : FOR( i = 0; i < crossOverFreq; i++ )
1398 : {
1399 576136 : IF( concealment_noise[i] > 0 )
1400 : {
1401 300265 : mdctSpectrum[i] = L_shl( L_deposit_l( hTonalMDCTConc->lastBlockData.spectralData[i] ), 16 ); // Q31-spectralData_exp
1402 300265 : move32();
1403 : }
1404 : ELSE
1405 : {
1406 275871 : mdctSpectrum[i] = L_negate( L_shl( L_deposit_l( hTonalMDCTConc->lastBlockData.spectralData[i] ), 16 ) ); // Q31-spectralData_exp
1407 275871 : move32();
1408 : }
1409 : }
1410 :
1411 372868 : FOR( l = crossOverFreq; l < hTonalMDCTConc->lastBlockData.nSamples; l++ )
1412 : {
1413 371384 : mdctSpectrum[l] = 0;
1414 371384 : move32();
1415 : }
1416 :
1417 1484 : *mdctSpectrum_exp = hTonalMDCTConc->lastBlockData.spectralData_exp;
1418 1484 : move16();
1419 : }
1420 : /* actual fadeout is done in this case */
1421 : ELSE
1422 : {
1423 : Word32 num, den;
1424 : Word16 exp_num, exp_den;
1425 :
1426 1529 : exp_num = cngLevelBackgroundTrace_bfi_e;
1427 1529 : move16();
1428 1529 : exp_den = hTonalMDCTConc->curr_noise_nrg_exp;
1429 1529 : move16();
1430 :
1431 1529 : ld = norm_l( cngLevelBackgroundTrace_bfi );
1432 1529 : num = L_shl( cngLevelBackgroundTrace_bfi, ld );
1433 1529 : exp_num = sub( exp_num, ld );
1434 1529 : ld = norm_l( hTonalMDCTConc->curr_noise_nrg );
1435 1529 : den = L_shl( hTonalMDCTConc->curr_noise_nrg, ld ); // Q31- curr_noise_nrg_exp + ld
1436 1529 : exp_den = sub( exp_den, ld );
1437 :
1438 1529 : exp = sub( exp_num, exp_den );
1439 :
1440 1529 : IF( GT_32( num, den ) )
1441 : {
1442 1497 : num = L_shr( num, 1 ); // Q31-exp -1
1443 1497 : exp = add( exp, 1 );
1444 : }
1445 1529 : tmp = div_l( num, round_fx_sat( den ) );
1446 1529 : tmp = Sqrt16( tmp, &exp );
1447 1529 : g = mult_r( g, tmp ); // exponent of g = exp
1448 :
1449 1529 : L_tmp = L_deposit_h( 0 );
1450 1529 : exp = sub( hTonalMDCTConc->lastBlockData.spectralData_exp, add( concealment_noise_e, exp ) );
1451 1529 : (void) maximum_abs_32_fx( concealment_noise, crossOverFreq, &max_concealment_value );
1452 1529 : IF( GT_32( max_concealment_value, 0 ) )
1453 : {
1454 139 : IF( exp > 0 )
1455 : {
1456 121 : g = shr( g, exp ); // Q15-exp
1457 121 : *mdctSpectrum_exp = hTonalMDCTConc->lastBlockData.spectralData_exp;
1458 121 : move16();
1459 : }
1460 : ELSE
1461 : {
1462 18 : crossfadeGain = shl( crossfadeGain, exp ); // Q15 - e_crossfadeGain + exp
1463 18 : e_crossfadeGain = sub( e_crossfadeGain, exp );
1464 18 : *mdctSpectrum_exp = sub( hTonalMDCTConc->lastBlockData.spectralData_exp, exp );
1465 18 : move16();
1466 : }
1467 : /*make a headroom for mdct_shaping*/
1468 139 : exp = sub( *mdctSpectrum_exp, SPEC_EXP_DEC );
1469 : /* assert(exp < 0);*/
1470 139 : IF( exp < 0 )
1471 : {
1472 139 : *mdctSpectrum_exp = SPEC_EXP_DEC;
1473 139 : move16();
1474 : }
1475 : ELSE
1476 : {
1477 0 : exp = 0;
1478 0 : move16();
1479 : }
1480 : }
1481 : ELSE
1482 : {
1483 1390 : (void) maximum_abs_16_fx( hTonalMDCTConc->lastBlockData.spectralData, crossOverFreq, &max_spectral_value );
1484 1390 : exp = sub( norm_l( L_mult( max_spectral_value, crossfadeGain ) ), find_guarded_bits_fx( crossOverFreq ) );
1485 1390 : *mdctSpectrum_exp = sub( hTonalMDCTConc->lastBlockData.spectralData_exp, exp );
1486 1390 : move16();
1487 : }
1488 :
1489 584633 : FOR( i = 0; i < crossOverFreq; i++ )
1490 : {
1491 583104 : Word16 x = hTonalMDCTConc->lastBlockData.spectralData[i]; // Q15 - spectralData_exp
1492 583104 : move16();
1493 583104 : Word32 y = concealment_noise[i]; // Q31-concealment_noise_e
1494 583104 : move32();
1495 :
1496 583104 : IF( g > 0 )
1497 : {
1498 579936 : L_tmp = Mpy_32_16_1( y, g ); // Q31-concealment_noise_e- spectralData_exp
1499 : }
1500 :
1501 583104 : L_tmp2 = L_msu( L_tmp, crossfadeGain, x ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp
1502 583104 : IF( y > 0 )
1503 : {
1504 27877 : L_tmp2 = L_mac( L_tmp, crossfadeGain, x ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp
1505 : }
1506 583104 : mdctSpectrum[i] = L_shl( L_tmp2, exp ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp + exp
1507 583104 : move32();
1508 :
1509 583104 : hTonalMDCTConc->faded_signal_nrg = L_add( hTonalMDCTConc->faded_signal_nrg, Mpy_32_32( mdctSpectrum[i], mdctSpectrum[i] ) ); // Q31- faded_signal_nrg_exp
1510 583104 : move32();
1511 : }
1512 402105 : FOR( i = crossOverFreq; i < hTonalMDCTConc->lastBlockData.nSamples; i++ )
1513 : {
1514 400576 : mdctSpectrum[i] = 0;
1515 400576 : move32();
1516 : }
1517 1529 : *mdctSpectrum_exp = sub( add( e_crossfadeGain, hTonalMDCTConc->lastBlockData.spectralData_exp ), exp );
1518 1529 : move16();
1519 1529 : hTonalMDCTConc->faded_signal_nrg_exp = shl( *mdctSpectrum_exp, 1 );
1520 1529 : move16();
1521 : }
1522 : }
1523 : ELSE
1524 : {
1525 95 : assert( hTonalMDCTConc->pTCI->numIndexes > 0 );
1526 :
1527 : /* initialize bins of tonal components with zero: basically not
1528 : necessary, but currently the whole spectrum is rescaled in
1529 : mdct_noiseShaping() and then there would be a processing of
1530 : uninitialized values */
1531 :
1532 95 : ld = sub( 14, norm_s( hTonalMDCTConc->lastBlockData.nSamples ) );
1533 95 : fac = shr( -32768, ld );
1534 :
1535 762 : FOR( i = 0; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
1536 : {
1537 5336 : FOR( l = hTonalMDCTConc->pTCI->lowerIndex[i]; l <= hTonalMDCTConc->pTCI->upperIndex[i]; l++ )
1538 : {
1539 4669 : mdctSpectrum[l] = L_deposit_h( 0 );
1540 4669 : IF( LT_16( l, crossOverFreq ) )
1541 : {
1542 4585 : Word16 x = hTonalMDCTConc->lastBlockData.spectralData[l];
1543 4585 : move16();
1544 4585 : Word32 y = concealment_noise[l]; // concealment_noise_e
1545 4585 : move32();
1546 4585 : shift1 = norm_l( y );
1547 4585 : y = L_shl( y, shift1 );
1548 :
1549 4585 : last_block_nrg_correct = L_add( last_block_nrg_correct, Mpy_32_16_1( L_msu( 0, x, fac ), x ) ); // exp = 2 * x_exp + ld
1550 4585 : y = L_negate( Mpy_32_32( y, y ) ); // Q31-(2* concealment_noise_e + shift1)
1551 4585 : hTonalMDCTConc->curr_noise_nrg = BASOP_Util_Add_Mant32Exp( hTonalMDCTConc->curr_noise_nrg, hTonalMDCTConc->curr_noise_nrg_exp, y, shl( sub( concealment_noise_e, shift1 ), 1 ), &hTonalMDCTConc->curr_noise_nrg_exp ); // Q31- hTonalMDCTConc->curr_noise_nrg_exp
1552 4585 : move32();
1553 : }
1554 : }
1555 : }
1556 95 : last_block_nrg_correct_e = add( shl( hTonalMDCTConc->lastBlockData.spectralData_exp, 1 ), ld );
1557 :
1558 : /* if fadeout has not started yet, only apply sign scrambling */
1559 95 : IF( GE_16( crossfadeGain_const, CROSSFADE_THRESHOLD ) )
1560 : {
1561 3983 : FOR( l = 0; l < hTonalMDCTConc->pTCI->lowerIndex[0]; l++ )
1562 : {
1563 3901 : IF( GT_32( concealment_noise[l], 0 ) )
1564 : {
1565 1845 : mdctSpectrum[l] = L_shl( L_deposit_l( hTonalMDCTConc->lastBlockData.spectralData[l] ), 16 ); // hTonalMDCTConc->lastBlockData.spectralData_exp
1566 1845 : move32();
1567 : }
1568 : ELSE
1569 : {
1570 2056 : mdctSpectrum[l] = L_negate( L_shl( L_deposit_l( hTonalMDCTConc->lastBlockData.spectralData[l] ), 16 ) ); // hTonalMDCTConc->lastBlockData.spectralData_exp
1571 2056 : move32();
1572 : }
1573 : }
1574 592 : FOR( i = 1; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
1575 : {
1576 7988 : FOR( l = hTonalMDCTConc->pTCI->upperIndex[i - 1] + 1; l < hTonalMDCTConc->pTCI->lowerIndex[i]; l++ )
1577 : {
1578 7478 : IF( concealment_noise[l] > 0 )
1579 : {
1580 4003 : mdctSpectrum[l] = L_shl( L_deposit_l( hTonalMDCTConc->lastBlockData.spectralData[l] ), 16 ); // hTonalMDCTConc->lastBlockData.spectralData_exp
1581 4003 : move32();
1582 : }
1583 : ELSE
1584 : {
1585 3475 : mdctSpectrum[l] = L_negate( L_shl( L_deposit_l( hTonalMDCTConc->lastBlockData.spectralData[l] ), 16 ) ); // hTonalMDCTConc->lastBlockData.spectralData_exp
1586 3475 : move32();
1587 : }
1588 : }
1589 : }
1590 :
1591 18696 : FOR( l = hTonalMDCTConc->pTCI->upperIndex[hTonalMDCTConc->pTCI->numIndexes - 1] + 1; l < crossOverFreq; l++ )
1592 : {
1593 18614 : IF( concealment_noise[l] > 0 )
1594 : {
1595 9589 : mdctSpectrum[l] = L_shl( L_deposit_l( hTonalMDCTConc->lastBlockData.spectralData[l] ), 16 ); // hTonalMDCTConc->lastBlockData.spectralData_exp
1596 9589 : move32();
1597 : }
1598 : ELSE
1599 : {
1600 9025 : mdctSpectrum[l] = L_negate( L_shl( L_deposit_l( hTonalMDCTConc->lastBlockData.spectralData[l] ), 16 ) ); // hTonalMDCTConc->lastBlockData.spectralData_exp
1601 9025 : move32();
1602 : }
1603 : }
1604 :
1605 21594 : FOR( l = crossOverFreq; l < hTonalMDCTConc->lastBlockData.nSamples; l++ )
1606 : {
1607 21512 : mdctSpectrum[l] = L_shl( L_deposit_l( hTonalMDCTConc->lastBlockData.spectralData[l] ), 16 ); // hTonalMDCTConc->lastBlockData.spectralData_exp
1608 21512 : move32();
1609 : }
1610 :
1611 82 : *mdctSpectrum_exp = hTonalMDCTConc->lastBlockData.spectralData_exp;
1612 82 : move16();
1613 : }
1614 : /* actual fadeout is done in this case */
1615 : ELSE
1616 : {
1617 13 : tmp = BASOP_Util_Divide3232_Scale( cngLevelBackgroundTrace_bfi, hTonalMDCTConc->curr_noise_nrg, &exp );
1618 13 : exp = add( exp, sub( cngLevelBackgroundTrace_bfi_e, hTonalMDCTConc->curr_noise_nrg_exp ) );
1619 :
1620 13 : tmp = Sqrt16( tmp, &exp );
1621 13 : g = mult_r( g, tmp ); // exponent of g = exp
1622 :
1623 13 : L_tmp = L_deposit_h( 0 );
1624 13 : exp = sub( hTonalMDCTConc->lastBlockData.spectralData_exp, add( concealment_noise_e, exp ) );
1625 :
1626 13 : (void) maximum_abs_32_fx( concealment_noise, crossOverFreq, &max_concealment_value );
1627 13 : IF( GT_32( max_concealment_value, 0 ) )
1628 : {
1629 0 : IF( GT_16( exp, 0 ) )
1630 : {
1631 0 : g = shr( g, exp ); // Q15- exp
1632 0 : *mdctSpectrum_exp = hTonalMDCTConc->lastBlockData.spectralData_exp;
1633 0 : move16();
1634 : }
1635 : ELSE
1636 : {
1637 0 : crossfadeGain = shl( crossfadeGain, exp ); // Q15 - e_crossfadeGain
1638 0 : e_crossfadeGain = sub( e_crossfadeGain, exp );
1639 0 : *mdctSpectrum_exp = add( e_crossfadeGain, hTonalMDCTConc->lastBlockData.spectralData_exp );
1640 0 : move16();
1641 : }
1642 : /*make a headroom for mdct_shaping*/
1643 0 : exp = sub( *mdctSpectrum_exp, SPEC_EXP_DEC );
1644 : /* assert(exp < 0);*/
1645 0 : IF( exp < 0 )
1646 : {
1647 0 : *mdctSpectrum_exp = SPEC_EXP_DEC;
1648 0 : move16();
1649 : }
1650 : ELSE
1651 : {
1652 0 : exp = 0;
1653 0 : move16();
1654 : }
1655 : }
1656 : ELSE
1657 : {
1658 13 : (void) maximum_abs_16_fx( hTonalMDCTConc->lastBlockData.spectralData, crossOverFreq, &max_spectral_value );
1659 13 : exp = sub( norm_l( L_mult( max_spectral_value, crossfadeGain ) ), find_guarded_bits_fx( crossOverFreq ) );
1660 13 : *mdctSpectrum_exp = sub( hTonalMDCTConc->lastBlockData.spectralData_exp, exp );
1661 13 : move16();
1662 : }
1663 :
1664 1054 : FOR( l = 0; l < hTonalMDCTConc->pTCI->lowerIndex[0]; l++ )
1665 : {
1666 1041 : Word16 x = hTonalMDCTConc->lastBlockData.spectralData[l]; // Q15 - spectralData_exp
1667 1041 : move16();
1668 1041 : Word32 y = concealment_noise[l]; // Q31-concealment_noise_e
1669 1041 : move32();
1670 :
1671 1041 : IF( g > 0 )
1672 : {
1673 1041 : L_tmp = Mpy_32_16_1( y, g ); // Q31-concealment_noise_e- spectralData_exp
1674 : }
1675 :
1676 1041 : L_tmp2 = L_msu( L_tmp, crossfadeGain, x ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp
1677 1041 : IF( y > 0 )
1678 : {
1679 0 : L_tmp2 = L_mac( L_tmp, crossfadeGain, x ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp
1680 : }
1681 1041 : mdctSpectrum[l] = L_shl( L_tmp2, exp ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp + exp
1682 1041 : move32();
1683 :
1684 1041 : hTonalMDCTConc->faded_signal_nrg = L_add( hTonalMDCTConc->faded_signal_nrg, Mpy_32_32( mdctSpectrum[l], mdctSpectrum[l] ) ); // Q31 - 2*mdctSpectrum_exp
1685 1041 : move32();
1686 : }
1687 :
1688 75 : FOR( i = 1; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
1689 : {
1690 1207 : FOR( l = hTonalMDCTConc->pTCI->upperIndex[i - 1] + 1; l < hTonalMDCTConc->pTCI->lowerIndex[i]; l++ )
1691 : {
1692 1145 : Word16 x = hTonalMDCTConc->lastBlockData.spectralData[l]; // Q15 - spectralData_exp
1693 1145 : move16();
1694 1145 : Word32 y = concealment_noise[l]; // Q31-concealment_noise_e
1695 1145 : move32();
1696 :
1697 1145 : L_tmp = Mpy_32_16_1( y, g );
1698 1145 : L_tmp2 = L_msu( L_tmp, crossfadeGain, x ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp
1699 1145 : IF( y > 0 )
1700 : {
1701 0 : L_tmp2 = L_mac( L_tmp, crossfadeGain, x ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp
1702 : }
1703 1145 : mdctSpectrum[l] = L_shl( L_tmp2, exp ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp + exp
1704 1145 : move32();
1705 :
1706 1145 : hTonalMDCTConc->faded_signal_nrg = L_add( hTonalMDCTConc->faded_signal_nrg, Mpy_32_32( mdctSpectrum[l], mdctSpectrum[l] ) ); // Q31- 2*mdctSpectrum_exp
1707 : }
1708 : }
1709 :
1710 2902 : FOR( l = hTonalMDCTConc->pTCI->upperIndex[hTonalMDCTConc->pTCI->numIndexes - 1] + 1; l < crossOverFreq; l++ )
1711 : {
1712 2889 : Word16 x = hTonalMDCTConc->lastBlockData.spectralData[l]; // Q15 - spectralData_exp
1713 2889 : move16();
1714 2889 : Word32 y = concealment_noise[l]; // Q31-concealment_noise_e
1715 2889 : move32();
1716 :
1717 2889 : L_tmp = Mpy_32_16_1( y, g ); // Q31-concealment_noise_e- spectralData_exp
1718 2889 : L_tmp2 = L_msu( L_tmp, crossfadeGain, x ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp
1719 2889 : IF( y > 0 )
1720 : {
1721 0 : L_tmp2 = L_mac( L_tmp, crossfadeGain, x ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp
1722 : }
1723 2889 : mdctSpectrum[l] = L_shl( L_tmp2, exp ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp + exp
1724 2889 : move32();
1725 :
1726 2889 : hTonalMDCTConc->faded_signal_nrg = L_add( hTonalMDCTConc->faded_signal_nrg, Mpy_32_32( mdctSpectrum[l], mdctSpectrum[l] ) ); // Q31- 2*mdctSpectrum_exp
1727 2889 : move32();
1728 : }
1729 :
1730 2093 : FOR( l = crossOverFreq; l < hTonalMDCTConc->lastBlockData.nSamples; l++ )
1731 : {
1732 2080 : mdctSpectrum[l] = L_deposit_h( 0 );
1733 2080 : move32();
1734 : }
1735 :
1736 13 : hTonalMDCTConc->faded_signal_nrg_exp = shl( *mdctSpectrum_exp, 1 );
1737 13 : move16();
1738 : }
1739 : }
1740 :
1741 : // Compare curr_noise_nrg with MDCT_ST_PLC_FADEOUT_MIN_NOISE_NRG
1742 : Flag flag;
1743 3108 : flag = EQ_16( hTonalMDCTConc->curr_noise_nrg_exp, 0 ) && GT_32( hTonalMDCTConc->curr_noise_nrg, MDCT_ST_PLC_FADEOUT_MIN_NOISE_NRG_Q31 );
1744 3108 : flag = flag || GT_16( hTonalMDCTConc->curr_noise_nrg_exp, 0 );
1745 3108 : test();
1746 3108 : IF( GT_32( hTonalMDCTConc->faded_signal_nrg, 0 ) && flag )
1747 : {
1748 : Word16 num_exp;
1749 : Word32 num;
1750 :
1751 73 : num = BASOP_Util_Add_Mant32Exp( hTonalMDCTConc->last_block_nrg, hTonalMDCTConc->last_block_nrg_exp, L_negate( last_block_nrg_correct ), last_block_nrg_correct_e, &num_exp ); // Q31-num_exp
1752 73 : tmp = BASOP_Util_Divide3232_Scale( num, hTonalMDCTConc->faded_signal_nrg, &exp );
1753 73 : exp = add( exp, sub( num_exp, hTonalMDCTConc->faded_signal_nrg_exp ) );
1754 73 : tmp = Sqrt16( tmp, &exp );
1755 :
1756 28105 : FOR( i = 0; i < crossOverFreq; i++ )
1757 : {
1758 28032 : mdctSpectrum[i] = Mpy_32_16_1( mdctSpectrum[i], tmp ); // Q31-(*mdctSpectrum_exp+exp)
1759 28032 : move32();
1760 : }
1761 73 : *mdctSpectrum_exp = add( *mdctSpectrum_exp, exp );
1762 : }
1763 : }
1764 : ELSE{
1765 5625 : IF( tonalConcealmentActive == 0 ){
1766 5243 : sum1 = 0;
1767 5243 : sum2 = 0;
1768 5243 : move64();
1769 5243 : move64();
1770 2429037 : FOR( i = 0; i < crossOverFreq; i++ )
1771 : {
1772 : Word16 x;
1773 : /*x = hTonalMDCTConc->lastBlockData.spectralData[i];
1774 : nrgNoiseInLastFrame += x * x;*/
1775 2423794 : sum1 = W_mac0_16_16( sum1, hTonalMDCTConc->lastBlockData.spectralData[i], hTonalMDCTConc->lastBlockData.spectralData[i] ); // Q: 2*(15-hTonalMDCTConc->lastBlockData.spectralData_exp)
1776 :
1777 : /* rnd = own_random(&rnd); */
1778 2423794 : rnd = extract_l( L_mac0( 13849, rnd, 31821 ) ); /* Q0 */
1779 :
1780 : /* mdctSpectrum[i] = tilt * rnd; */
1781 2423794 : mdctSpectrum[i] = L_mult( tilt, rnd ); // Q16
1782 2423794 : move32();
1783 :
1784 : /* tilt *= tiltFactor; */
1785 2423794 : tilt = mult_r( tilt, tiltFactor ); /* Q15 */
1786 :
1787 : /* nrgWhiteNoise += mdctSpectrum[i] * mdctSpectrum[i]; */
1788 2423794 : x = round_fx( mdctSpectrum[i] ); // Q0
1789 2423794 : sum2 = W_mac0_16_16( sum2, x, x ); // Q0
1790 : }
1791 5243 : *mdctSpectrum_exp = 15;
1792 5243 : move16();
1793 :
1794 5243 : IF( sum1 /* nrgNoiseInLastFrame */ == 0 )
1795 : {
1796 1 : set32_fx( mdctSpectrum, 0, crossOverFreq );
1797 1 : *mdctSpectrum_exp = SPEC_EXP_DEC;
1798 1 : move16();
1799 : }
1800 : ELSE
1801 : {
1802 5242 : IF( g == 0 )
1803 : {
1804 4141 : *mdctSpectrum_exp = add( add( hTonalMDCTConc->lastBlockData.spectralData_exp, e_crossfadeGain ), 31 - SPEC_EXP_DEC );
1805 4141 : move16();
1806 2115181 : FOR( i = 0; i < crossOverFreq; i++ )
1807 : {
1808 : /* mdctSpectrum[i] = g * mdctSpectrum[i] + crossfadeGain * hTonalMDCTConc->lastBlockData.spectralData[i]; */
1809 2111040 : L_tmp = L_mult( crossfadeGain, hTonalMDCTConc->lastBlockData.spectralData[i] ); // exp: hTonalMDCTConc->lastBlockData.spectralData_exp+e_crossfadeGain
1810 2111040 : if ( mdctSpectrum[i] <= 0 )
1811 : {
1812 : /* mdctSpectrum[i] = g * mdctSpectrum[i] - crossfadeGain * hTonalMDCTConc->lastBlockData.spectralData[i]; */
1813 1056378 : L_tmp = L_negate( L_tmp ); // exp: hTonalMDCTConc->lastBlockData.spectralData_exp+e_crossfadeGain
1814 : }
1815 : /* headroom for mdct_shaping */
1816 2111040 : mdctSpectrum[i] = L_shr( L_tmp, 31 - SPEC_EXP_DEC ); // *mdctSpectrum_exp
1817 2111040 : move32();
1818 : }
1819 : }
1820 : ELSE
1821 : {
1822 1101 : IF( sum2 /* nrgWhiteNoise */ > 0 )
1823 : {
1824 1101 : exp1 = sub( W_norm( sum1 ), 1 );
1825 1101 : num16 = extract_h( W_extract_h( W_shl( sum1, exp1 ) ) ); // nrgNoiseInLastFrame -> Q: 2*(15-hTonalMDCTConc->lastBlockData.spectralData_exp)+exp1-48
1826 1101 : exp2 = W_norm( sum2 );
1827 1101 : den16 = extract_h( W_extract_h( W_shl( sum2, exp2 ) ) ); // nrgWhiteNoise -> Q: exp2-48
1828 :
1829 : /* sqrt( nrgNoiseInLastFrame / nrgWhiteNoise ) */
1830 1101 : tmp = div_s( num16, den16 ); // Q: 15+(2*(15-hTonalMDCTConc->lastBlockData.spectralData_exp)+exp1-48)-(exp2-48)
1831 1101 : exp = sub( sub( shl( hTonalMDCTConc->lastBlockData.spectralData_exp, 1 ), 30 ), sub( exp1, exp2 ) ); // exp of tmp
1832 1101 : tmp = Sqrt16( tmp, &exp );
1833 1101 : g = mult_r( g, tmp ); // exponent of g = exp
1834 : }
1835 :
1836 1101 : exp1 = add( *mdctSpectrum_exp, exp );
1837 1101 : exp2 = add( hTonalMDCTConc->lastBlockData.spectralData_exp, e_crossfadeGain );
1838 1101 : exp = add( s_max( exp1, exp2 ), 1 );
1839 1101 : shift1 = sub( exp1, exp );
1840 1101 : shift2 = sub( exp2, exp );
1841 :
1842 313535 : FOR( i = 0; i < crossOverFreq; i++ )
1843 : {
1844 312434 : L_tmp1 = L_shl( Mpy_32_16_1( mdctSpectrum[i], g ), shift1 ); // g * mdctSpectrum[i]
1845 312434 : L_tmp2 = L_shl( L_mult( crossfadeGain, hTonalMDCTConc->lastBlockData.spectralData[i] ), shift2 ); // exp
1846 :
1847 : /* mdctSpectrum[i] = g * mdctSpectrum[i] - crossfadeGain * hTonalMDCTConc->lastBlockData.spectralData[i]; */
1848 312434 : L_tmp = L_sub( L_tmp1, L_tmp2 ); // exp
1849 312434 : if ( mdctSpectrum[i] > 0 )
1850 : {
1851 : /* mdctSpectrum[i] = g * mdctSpectrum[i] + crossfadeGain * hTonalMDCTConc->lastBlockData.spectralData[i]; */
1852 160342 : L_tmp = L_add( L_tmp1, L_tmp2 ); // exp
1853 : }
1854 312434 : mdctSpectrum[i] = L_shr( L_tmp, 31 - SPEC_EXP_DEC ); // exp+31-SPEC_EXP_DEC
1855 312434 : move32();
1856 : }
1857 : /* headroom for mdct_shaping */
1858 1101 : *mdctSpectrum_exp = add( exp, 31 - SPEC_EXP_DEC );
1859 1101 : move16();
1860 : }
1861 : }
1862 5243 : exp = sub( hTonalMDCTConc->lastBlockData.spectralData_exp, *mdctSpectrum_exp );
1863 1358009 : FOR( i = crossOverFreq; i < hTonalMDCTConc->lastBlockData.nSamples; i++ )
1864 : {
1865 1352766 : mdctSpectrum[i] = L_shl( L_deposit_h( hTonalMDCTConc->lastBlockData.spectralData[i] ), exp ); // mdctSpectrum_exp
1866 1352766 : move32();
1867 : }
1868 : }
1869 : ELSE
1870 : {
1871 382 : assert( hTonalMDCTConc->pTCI->numIndexes > 0 );
1872 3047 : FOR( l = hTonalMDCTConc->pTCI->lowerIndex[0]; l <= hTonalMDCTConc->pTCI->upperIndex[0]; l++ )
1873 : {
1874 2665 : mdctSpectrum[l] = L_deposit_l( 0 );
1875 : }
1876 :
1877 382 : ld = sub( 14, norm_s( hTonalMDCTConc->lastBlockData.nSamples ) );
1878 382 : fac = shr( -32768, ld );
1879 24129 : FOR( l = 0; l < hTonalMDCTConc->pTCI->lowerIndex[0]; l++ )
1880 : {
1881 23747 : Word16 x = hTonalMDCTConc->lastBlockData.spectralData[l]; // Q15 - spectralData_exp
1882 23747 : move16();
1883 : Word32 y;
1884 :
1885 23747 : rnd = extract_l( L_mac0( 13849, rnd, 31821 ) ); // Q0
1886 23747 : y = L_mult( tilt, rnd ); // 15Q16
1887 :
1888 23747 : nrgNoiseInLastFrame = L_add( nrgNoiseInLastFrame, Mpy_32_16_1( L_msu( 0, x, fac ), x ) ); // Q(31 - x_exp - ld) + Q(15 - x_exp) - 15 = Q(31 - x_exp * 2 - ld)
1889 23747 : x = round_fx( y ); // 15Q16 -> Q15
1890 23747 : nrgWhiteNoise = L_add( nrgWhiteNoise, Mpy_32_16_1( L_msu( 0, x, fac ), x ) ); // Q(31 - (15 - 0) - ld) + Q(0) - 15 = Q(1 - ld)
1891 :
1892 23747 : mdctSpectrum[l] = y; /* 15Q16 L_deposit_l(y);*/
1893 23747 : move32();
1894 :
1895 23747 : tilt = mult_r( tilt, tiltFactor ); /* Q15 */
1896 : }
1897 :
1898 1880 : FOR( i = 1; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
1899 : {
1900 1498 : tmp = round_fx( BASOP_Util_fPow( L_deposit_h( tiltFactor ), 0, L_deposit_h( (UWord16) L_add( L_sub( hTonalMDCTConc->pTCI->upperIndex[i - 1], hTonalMDCTConc->pTCI->lowerIndex[i - 1] ), 1 ) ), 15, &exp ) );
1901 1498 : tmp = shl_sat( tmp, exp );
1902 1498 : tilt = mult_r( tilt, tmp ); // Q15
1903 :
1904 11954 : FOR( l = hTonalMDCTConc->pTCI->lowerIndex[i]; l <= hTonalMDCTConc->pTCI->upperIndex[i]; l++ )
1905 : {
1906 10456 : mdctSpectrum[l] = L_deposit_l( 0 );
1907 10456 : move32();
1908 : }
1909 24083 : FOR( l = hTonalMDCTConc->pTCI->upperIndex[i - 1] + 1; l < hTonalMDCTConc->pTCI->lowerIndex[i]; l++ )
1910 : {
1911 22585 : Word16 x = hTonalMDCTConc->lastBlockData.spectralData[l]; // Q15 - spectralData_exp
1912 22585 : move16();
1913 : Word32 y;
1914 :
1915 22585 : rnd = extract_l( L_mac0( 13849, rnd, 31821 ) ); // Q0
1916 22585 : y = L_mult( tilt, rnd ); // 15Q16
1917 :
1918 22585 : nrgNoiseInLastFrame = L_add( nrgNoiseInLastFrame, Mpy_32_16_1( L_msu( 0, x, fac ), x ) ); // Q(31 - hTonalMDCTConc->lastBlockData.spectralData_exp * 2 - ld)
1919 22585 : x = round_fx( y ); // Q15
1920 22585 : nrgWhiteNoise = L_add( nrgWhiteNoise, Mpy_32_16_1( L_msu( 0, x, fac ), x ) ); // Q(1 - ld)
1921 :
1922 22585 : mdctSpectrum[l] = y; /* 15Q16 L_deposit_l(y);*/
1923 22585 : move32();
1924 :
1925 22585 : tilt = mult_r( tilt, tiltFactor ); // Q15
1926 : }
1927 : }
1928 :
1929 382 : tmp = round_fx( BASOP_Util_fPow( L_deposit_h( tiltFactor ), 0,
1930 382 : L_deposit_h( extract_l( L_add( L_sub( hTonalMDCTConc->pTCI->upperIndex[hTonalMDCTConc->pTCI->numIndexes - 1], hTonalMDCTConc->pTCI->lowerIndex[hTonalMDCTConc->pTCI->numIndexes - 1] ), 1 ) ) ), 15, &exp ) );
1931 : BASOP_SATURATE_WARNING_OFF_EVS /*next op may result in 32768*/
1932 382 : tmp = shl_sat( tmp, exp );
1933 : BASOP_SATURATE_WARNING_ON_EVS
1934 382 : tilt = mult_r( tilt, tmp );
1935 :
1936 106185 : FOR( l = add( hTonalMDCTConc->pTCI->upperIndex[hTonalMDCTConc->pTCI->numIndexes - 1], 1 ); l < crossOverFreq; l++ )
1937 : {
1938 105803 : Word16 x = hTonalMDCTConc->lastBlockData.spectralData[l]; // Q15 - spectralData_exp
1939 105803 : move16();
1940 : Word32 y;
1941 105803 : rnd = extract_l( L_mac0( 13849, rnd, 31821 ) ); // Q0
1942 105803 : y = L_mult( tilt, rnd ); // 15Q16
1943 :
1944 105803 : nrgNoiseInLastFrame = L_add( nrgNoiseInLastFrame, Mpy_32_16_1( L_msu( 0, x, fac ), x ) ); // Q(31 - hTonalMDCTConc->lastBlockData.spectralData_exp * 2 - ld)
1945 105803 : x = round_fx( y ); // Q15
1946 105803 : nrgWhiteNoise = L_add( nrgWhiteNoise, Mpy_32_16_1( L_msu( 0, x, fac ), x ) ); // Q(1 - ld)
1947 :
1948 105803 : mdctSpectrum[l] = y; /* 15Q16 L_deposit_l(y);*/
1949 105803 : move32();
1950 :
1951 105803 : tilt = mult_r( tilt, tiltFactor ); // Q15
1952 : }
1953 :
1954 382 : IF( EQ_32( nrgNoiseInLastFrame, 0 ) )
1955 : {
1956 0 : set32_fx( mdctSpectrum, 0, crossOverFreq );
1957 0 : *mdctSpectrum_exp = SPEC_EXP_DEC;
1958 0 : move16();
1959 : }
1960 : ELSE
1961 : {
1962 382 : exp_last = add( ld, shl( hTonalMDCTConc->lastBlockData.spectralData_exp, 1 ) );
1963 382 : exp_noise = add( ld, shl( 15, 1 ) );
1964 :
1965 382 : ld = norm_l( nrgNoiseInLastFrame );
1966 382 : nrgNoiseInLastFrame = L_shl( nrgNoiseInLastFrame, ld ); // Q31-exp_last+ld
1967 382 : exp_last = sub( exp_last, ld );
1968 382 : ld = norm_l( nrgWhiteNoise );
1969 382 : nrgWhiteNoise = L_shl( nrgWhiteNoise, ld ); // Q31 - exp_noise + ld
1970 382 : exp_noise = sub( exp_noise, ld );
1971 :
1972 382 : exp = sub( exp_last, exp_noise );
1973 :
1974 382 : IF( GT_32( nrgNoiseInLastFrame, nrgWhiteNoise ) )
1975 : {
1976 198 : nrgNoiseInLastFrame = L_shr( nrgNoiseInLastFrame, 1 ); // Q31 - Qexp -1
1977 198 : exp = add( exp, 1 );
1978 : }
1979 382 : tmp = div_l( nrgNoiseInLastFrame, extract_h( nrgWhiteNoise ) );
1980 382 : tmp = Sqrt16( tmp, &exp );
1981 382 : g = mult_r( g, tmp );
1982 :
1983 382 : L_tmp = L_deposit_h( 0 );
1984 382 : ld = sub( hTonalMDCTConc->lastBlockData.spectralData_exp, 15 );
1985 382 : exp = sub( ld, exp );
1986 382 : IF( exp > 0 )
1987 : {
1988 382 : g = shr( g, exp ); // Q15 - exp
1989 382 : *mdctSpectrum_exp = hTonalMDCTConc->lastBlockData.spectralData_exp;
1990 382 : move16();
1991 : }
1992 : ELSE
1993 : {
1994 0 : crossfadeGain = shl( crossfadeGain, exp );
1995 0 : e_crossfadeGain = sub( e_crossfadeGain, exp );
1996 0 : *mdctSpectrum_exp = add( e_crossfadeGain, hTonalMDCTConc->lastBlockData.spectralData_exp );
1997 0 : move16();
1998 : }
1999 : /*make a headroom for mdct_shaping*/
2000 382 : exp = sub( *mdctSpectrum_exp, SPEC_EXP_DEC );
2001 :
2002 382 : IF( exp < 0 )
2003 : {
2004 382 : *mdctSpectrum_exp = SPEC_EXP_DEC;
2005 382 : move16();
2006 : }
2007 : ELSE
2008 : {
2009 0 : exp = 0;
2010 0 : move16();
2011 : }
2012 :
2013 24129 : FOR( l = 0; l < hTonalMDCTConc->pTCI->lowerIndex[0]; l++ )
2014 : {
2015 23747 : Word16 const x = hTonalMDCTConc->lastBlockData.spectralData[l]; // Q15 - spectralData_exp
2016 23747 : move16();
2017 23747 : Word32 const y = mdctSpectrum[l]; // Q31-mdctSpectrum_exp
2018 23747 : move32();
2019 :
2020 23747 : IF( g > 0 )
2021 : {
2022 5082 : L_tmp = Mpy_32_16_1( y, g ); // Q31-mdctSpectrum_exp- spectralData_exp
2023 : }
2024 :
2025 23747 : L_tmp2 = L_msu( L_tmp, crossfadeGain, x ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp
2026 23747 : IF( y > 0 )
2027 : {
2028 12223 : L_tmp2 = L_mac( L_tmp, crossfadeGain, x ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp
2029 : }
2030 23747 : mdctSpectrum[l] = L_shl( L_tmp2, exp ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp + exp
2031 23747 : move32();
2032 : }
2033 :
2034 1880 : FOR( i = 1; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
2035 : {
2036 24083 : FOR( l = hTonalMDCTConc->pTCI->upperIndex[i - 1] + 1; l < hTonalMDCTConc->pTCI->lowerIndex[i]; l++ )
2037 : {
2038 22585 : Word16 const x = hTonalMDCTConc->lastBlockData.spectralData[l]; // Q15 - spectralData_exp
2039 22585 : move16();
2040 22585 : Word32 const y = mdctSpectrum[l]; // Q31-mdctSpectrum_exp
2041 22585 : move32();
2042 :
2043 22585 : IF( g > 0 )
2044 : {
2045 3433 : L_tmp = Mpy_32_16_1( y, g ); // Q31-mdctSpectrum_exp- spectralData_exp
2046 : }
2047 :
2048 22585 : L_tmp2 = L_msu( L_tmp, crossfadeGain, x ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp
2049 22585 : IF( y > 0 )
2050 : {
2051 12680 : L_tmp2 = L_mac( L_tmp, crossfadeGain, x ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp
2052 : }
2053 22585 : mdctSpectrum[l] = L_shl( L_tmp2, exp ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp + exp
2054 22585 : move32();
2055 : }
2056 : }
2057 :
2058 : /* initialize bins of tonal components with zero: basically not
2059 : necessary, but currently the whole spectrum is rescaled in
2060 : mdct_noiseShaping() and then there would be a processing of
2061 : uninitialized values */
2062 2262 : FOR( i = 0; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
2063 : {
2064 15001 : FOR( l = hTonalMDCTConc->pTCI->lowerIndex[i]; l <= hTonalMDCTConc->pTCI->upperIndex[i]; l++ )
2065 : {
2066 13121 : mdctSpectrum[l] = L_deposit_l( 0 );
2067 13121 : move32();
2068 : }
2069 : }
2070 :
2071 106185 : FOR( l = add( hTonalMDCTConc->pTCI->upperIndex[hTonalMDCTConc->pTCI->numIndexes - 1], 1 ); l < crossOverFreq; l++ )
2072 : {
2073 105803 : Word16 const x = hTonalMDCTConc->lastBlockData.spectralData[l]; // Q15 - spectralData_exp
2074 105803 : move16();
2075 105803 : Word32 const y = mdctSpectrum[l]; // Q31-mdctSpectrum_exp
2076 105803 : move32();
2077 :
2078 105803 : IF( GT_16( g, 0 ) )
2079 : {
2080 17502 : L_tmp = Mpy_32_16_1( y, g ); // Q31-mdctSpectrum_exp- spectralData_exp
2081 : }
2082 :
2083 105803 : L_tmp2 = L_msu( L_tmp, crossfadeGain, x ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp
2084 105803 : IF( GT_32( y, 0 ) )
2085 : {
2086 52128 : L_tmp2 = L_mac( L_tmp, crossfadeGain, x ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp
2087 : }
2088 105803 : mdctSpectrum[l] = L_shl( L_tmp2, exp ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp + exp
2089 105803 : move32();
2090 : }
2091 : }
2092 382 : exp = sub( hTonalMDCTConc->lastBlockData.spectralData_exp, sub( *mdctSpectrum_exp, 16 ) );
2093 169206 : FOR( l = crossOverFreq; l < hTonalMDCTConc->lastBlockData.nSamples; l++ )
2094 : {
2095 168824 : mdctSpectrum[l] = L_shl( L_deposit_l( hTonalMDCTConc->lastBlockData.spectralData[l] ), exp ); // Q15 - spectralData_exp
2096 168824 : move32();
2097 : }
2098 : }
2099 : }
2100 :
2101 8733 : *pSeed = rnd;
2102 8733 : move16();
2103 :
2104 8733 : pop_wmops();
2105 :
2106 8733 : return;
2107 : }
2108 :
2109 :
2110 0 : void TonalMDCTConceal_InsertNoise(
2111 : const TonalMDCTConcealPtr hTonalMDCTConc, /*IN */
2112 : Word32 *mdctSpectrum, // Q31- *mdctSpectrum_exp /*OUT*/
2113 : Word16 *mdctSpectrum_exp, /*OUT*/
2114 : const Word16 tonalConcealmentActive,
2115 : Word16 *pSeed, /*IN/OUT*/
2116 : const Word16 tiltCompFactor, // Q15
2117 : Word16 crossfadeGain, // Q15
2118 : const Word16 crossOverFreq )
2119 : {
2120 : Word16 i, ld, fac;
2121 : Word16 rnd, exp, exp_last, exp_noise, inv_samples, inv_exp;
2122 : Word16 g, tiltFactor, tilt, tmp;
2123 : Word32 nrgNoiseInLastFrame, nrgWhiteNoise, L_tmp, L_tmp2;
2124 :
2125 0 : g = sub( 32767 /*1.0f Q15*/, crossfadeGain );
2126 :
2127 0 : rnd = 1977;
2128 0 : move16();
2129 0 : if ( hTonalMDCTConc->lastBlockData.blockIsConcealed )
2130 : {
2131 0 : rnd = *pSeed;
2132 0 : move16();
2133 : }
2134 0 : IF( hTonalMDCTConc->lastBlockData.blockIsValid == 0 )
2135 : {
2136 : /* may just become active if the very first frame is lost */
2137 0 : set32_fx( mdctSpectrum, 0, hTonalMDCTConc->nSamples );
2138 0 : *mdctSpectrum_exp = SPEC_EXP_DEC;
2139 0 : move16();
2140 : }
2141 : ELSE
2142 : {
2143 0 : L_tmp = 805306368l /*0.375f Q31*/;
2144 0 : move32();
2145 0 : inv_exp = 15;
2146 0 : move16();
2147 0 : inv_samples = Inv16( hTonalMDCTConc->lastBlockData.nSamples, &inv_exp );
2148 0 : tiltFactor = round_fx( BASOP_Util_fPow( L_max( L_tmp, L_deposit_h( tiltCompFactor ) ), 0, L_deposit_h( inv_samples ), inv_exp, &exp ) );
2149 : BASOP_SATURATE_WARNING_OFF_EVS /*next op may result in 32768*/
2150 0 : tiltFactor = shl_sat( tiltFactor, exp ); // Q15- 2*exp
2151 : BASOP_SATURATE_WARNING_ON_EVS
2152 :
2153 0 : tilt = 32767 /*1.0f Q15*/;
2154 0 : move16();
2155 :
2156 0 : nrgNoiseInLastFrame = L_deposit_h( 0 );
2157 0 : nrgWhiteNoise = L_deposit_h( 0 );
2158 0 : exp_last = exp_noise = 0;
2159 0 : move16();
2160 0 : move16();
2161 0 : IF( !tonalConcealmentActive )
2162 : {
2163 0 : ld = sub( 14, norm_s( hTonalMDCTConc->lastBlockData.nSamples ) );
2164 0 : fac = shr( -32768, ld );
2165 :
2166 0 : FOR( i = 0; i < crossOverFreq; i++ )
2167 : {
2168 0 : Word16 x = hTonalMDCTConc->lastBlockData.spectralData[i]; // Q15 - spectralData_exp
2169 0 : move16();
2170 : Word32 y;
2171 0 : rnd = extract_l( L_mac0( 13849, rnd, 31821 ) ); // Q0
2172 0 : y = L_mult( tilt, rnd ); /* 15Q16 */
2173 :
2174 0 : nrgNoiseInLastFrame = L_add( nrgNoiseInLastFrame, Mpy_32_16_1( L_msu( 0, x, fac ), x ) ); // Q(31 - hTonalMDCTConc->lastBlockData.spectralData_exp * 2 - ld)
2175 0 : x = round_fx( y ); // Q15
2176 0 : nrgWhiteNoise = L_add( nrgWhiteNoise, Mpy_32_16_1( L_msu( 0, x, fac ), x ) ); // Q(1 - ld)
2177 :
2178 0 : mdctSpectrum[i] = y; /* 15Q16 */
2179 0 : move32();
2180 :
2181 0 : tilt = mult_r( tilt, tiltFactor ); // Q15
2182 : }
2183 :
2184 0 : IF( nrgNoiseInLastFrame == 0 )
2185 : {
2186 0 : set32_fx( mdctSpectrum, 0, crossOverFreq );
2187 0 : *mdctSpectrum_exp = SPEC_EXP_DEC;
2188 0 : move16();
2189 : }
2190 : ELSE
2191 : {
2192 0 : exp_last = add( ld, shl( hTonalMDCTConc->lastBlockData.spectralData_exp, 1 ) );
2193 0 : exp_noise = add( ld, 30 );
2194 :
2195 0 : IF( nrgWhiteNoise > 0 )
2196 : {
2197 0 : ld = norm_l( nrgNoiseInLastFrame );
2198 0 : nrgNoiseInLastFrame = L_shl( nrgNoiseInLastFrame, ld ); // Q31-exp_last + ld
2199 0 : exp_last = sub( exp_last, ld );
2200 0 : ld = norm_l( nrgWhiteNoise );
2201 0 : nrgWhiteNoise = L_shl( nrgWhiteNoise, ld ); // Q31-exp_noise + ld
2202 0 : exp_noise = sub( exp_noise, ld );
2203 :
2204 0 : exp = sub( exp_last, exp_noise );
2205 :
2206 0 : IF( GT_32( nrgNoiseInLastFrame, nrgWhiteNoise ) )
2207 : {
2208 0 : nrgNoiseInLastFrame = L_shr( nrgNoiseInLastFrame, 1 ); // Q31- exp - 1
2209 0 : exp = add( exp, 1 );
2210 : }
2211 0 : tmp = div_l( nrgNoiseInLastFrame, round_fx( nrgWhiteNoise ) );
2212 0 : tmp = Sqrt16( tmp, &exp );
2213 0 : g = mult_r( g, tmp );
2214 :
2215 0 : L_tmp = L_deposit_h( 0 );
2216 0 : ld = sub( hTonalMDCTConc->lastBlockData.spectralData_exp, 15 );
2217 0 : exp = sub( ld, exp );
2218 :
2219 0 : IF( exp > 0 )
2220 : {
2221 0 : g = shr( g, exp );
2222 0 : *mdctSpectrum_exp = hTonalMDCTConc->lastBlockData.spectralData_exp;
2223 0 : move16();
2224 : }
2225 : ELSE
2226 : {
2227 0 : crossfadeGain = shl( crossfadeGain, exp );
2228 0 : *mdctSpectrum_exp = sub( hTonalMDCTConc->lastBlockData.spectralData_exp, exp );
2229 : }
2230 : /*make a headroom for mdct_shaping*/
2231 0 : exp = sub( *mdctSpectrum_exp, SPEC_EXP_DEC );
2232 : /* assert(exp < 0);*/
2233 0 : IF( exp < 0 )
2234 : {
2235 0 : *mdctSpectrum_exp = SPEC_EXP_DEC;
2236 0 : move16();
2237 : }
2238 : ELSE
2239 : {
2240 0 : exp = 0;
2241 0 : move16();
2242 : }
2243 : }
2244 :
2245 0 : FOR( i = 0; i < crossOverFreq; i++ )
2246 : {
2247 0 : Word16 const x = hTonalMDCTConc->lastBlockData.spectralData[i];
2248 0 : move16();
2249 0 : Word32 const y = mdctSpectrum[i]; // Q31-mdctSpectrum_exp
2250 0 : move32();
2251 :
2252 0 : if ( g > 0 )
2253 : {
2254 0 : L_tmp = Mpy_32_16_1( y, g ); // Q31-mdctSpectrum_exp- spectralData_exp
2255 : }
2256 :
2257 0 : L_tmp2 = L_msu( L_tmp, crossfadeGain, x ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp
2258 0 : if ( y > 0 )
2259 : {
2260 0 : L_tmp2 = L_mac( L_tmp, crossfadeGain, x ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp
2261 : }
2262 0 : mdctSpectrum[i] = L_shl( L_tmp2, exp ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp + exp
2263 0 : move32();
2264 : }
2265 : }
2266 0 : exp = sub( hTonalMDCTConc->lastBlockData.spectralData_exp, sub( *mdctSpectrum_exp, 16 ) );
2267 0 : FOR( i = crossOverFreq; i < hTonalMDCTConc->lastBlockData.nSamples; i++ )
2268 : {
2269 0 : mdctSpectrum[i] = L_shl( L_deposit_l( hTonalMDCTConc->lastBlockData.spectralData[i] ), exp ); // Q15 - spectralData_exp + exp
2270 0 : move32();
2271 : }
2272 : }
2273 : ELSE
2274 : {
2275 : Word16 l;
2276 0 : assert( hTonalMDCTConc->pTCI->numIndexes > 0 );
2277 :
2278 0 : FOR( l = hTonalMDCTConc->pTCI->lowerIndex[0]; l <= hTonalMDCTConc->pTCI->upperIndex[0]; l++ )
2279 : {
2280 0 : mdctSpectrum[l] = L_deposit_l( 0 );
2281 0 : move32();
2282 : }
2283 :
2284 0 : ld = sub( 14, norm_s( hTonalMDCTConc->lastBlockData.nSamples ) );
2285 0 : fac = shr( -32768, ld );
2286 0 : FOR( l = 0; l < hTonalMDCTConc->pTCI->lowerIndex[0]; l++ )
2287 : {
2288 0 : Word16 x = hTonalMDCTConc->lastBlockData.spectralData[l]; // Q15 - spectralData_exp
2289 0 : move16();
2290 : Word32 y;
2291 0 : rnd = extract_l( L_mac0( 13849, rnd, 31821 ) ); // Q0
2292 0 : y = L_mult( tilt, rnd ); // 15Q16
2293 :
2294 0 : nrgNoiseInLastFrame = L_add( nrgNoiseInLastFrame, Mpy_32_16_1( L_msu( 0, x, fac ), x ) ); // Q(31 - hTonalMDCTConc->lastBlockData.spectralData_exp * 2 - ld)
2295 0 : x = round_fx( y ); // Q15
2296 0 : nrgWhiteNoise = L_add( nrgWhiteNoise, Mpy_32_16_1( L_msu( 0, x, fac ), x ) ); // Q(1-ld)
2297 :
2298 0 : mdctSpectrum[l] = y; /* 15Q16 L_deposit_l(y);*/
2299 0 : move32();
2300 :
2301 0 : tilt = mult_r( tilt, tiltFactor ); // Q15
2302 : }
2303 :
2304 0 : FOR( i = 1; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
2305 : {
2306 : /*tilt *= (float)pow(tiltFactor, hTonalMDCTConc->pTCI->upperIndex[i-1]-hTonalMDCTConc->pTCI->lowerIndex[i-1]+1);*/
2307 0 : tmp = round_fx( BASOP_Util_fPow( L_deposit_h( tiltFactor ), 0, L_deposit_h( (UWord16) L_add( L_sub( hTonalMDCTConc->pTCI->upperIndex[i - 1], hTonalMDCTConc->pTCI->lowerIndex[i - 1] ), 1 ) ), 15, &exp ) );
2308 0 : tmp = shl( tmp, exp );
2309 0 : tilt = mult_r( tilt, tmp );
2310 :
2311 0 : FOR( l = hTonalMDCTConc->pTCI->lowerIndex[i]; l <= hTonalMDCTConc->pTCI->upperIndex[i]; l++ )
2312 : {
2313 0 : mdctSpectrum[l] = L_deposit_l( 0 );
2314 0 : move32();
2315 : }
2316 :
2317 0 : FOR( l = hTonalMDCTConc->pTCI->upperIndex[i - 1] + 1; l < hTonalMDCTConc->pTCI->lowerIndex[i]; l++ )
2318 : {
2319 0 : Word16 x = hTonalMDCTConc->lastBlockData.spectralData[l]; // Q15 - spectralData_exp
2320 0 : move16();
2321 : Word32 y;
2322 0 : rnd = extract_l( L_mac0( 13849, rnd, 31821 ) ); // Q0
2323 0 : y = L_mult( tilt, rnd ); // 15Q16
2324 :
2325 0 : nrgNoiseInLastFrame = L_add( nrgNoiseInLastFrame, Mpy_32_16_1( L_msu( 0, x, fac ), x ) ); // Q(31 - hTonalMDCTConc->lastBlockData.spectralData_exp * 2 - ld)
2326 0 : x = round_fx( y ); // Q15
2327 0 : nrgWhiteNoise = L_add( nrgWhiteNoise, Mpy_32_16_1( L_msu( 0, x, fac ), x ) ); // Q(1-ld)
2328 :
2329 0 : mdctSpectrum[l] = y; /* 15Q16 L_deposit_l(y);*/
2330 0 : move32();
2331 :
2332 0 : tilt = mult_r( tilt, tiltFactor ); // Q15
2333 : }
2334 : }
2335 :
2336 0 : tmp = round_fx( BASOP_Util_fPow( L_deposit_h( tiltFactor ), 0, L_deposit_h( (UWord16) L_add( L_sub( hTonalMDCTConc->pTCI->upperIndex[hTonalMDCTConc->pTCI->numIndexes - 1], hTonalMDCTConc->pTCI->lowerIndex[hTonalMDCTConc->pTCI->numIndexes - 1] ), 1 ) ), 15, &exp ) );
2337 : BASOP_SATURATE_WARNING_OFF_EVS /*next op may result in 32768*/
2338 0 : tmp = shl_sat( tmp, exp ); // Q15 - 2*exp
2339 : BASOP_SATURATE_WARNING_ON_EVS
2340 0 : tilt = mult_r( tilt, tmp );
2341 :
2342 0 : FOR( l = add( hTonalMDCTConc->pTCI->upperIndex[hTonalMDCTConc->pTCI->numIndexes - 1], 1 ); l < crossOverFreq; l++ )
2343 : {
2344 0 : Word16 x = hTonalMDCTConc->lastBlockData.spectralData[l]; // Q15 - spectralData_exp
2345 0 : move16();
2346 : Word32 y;
2347 0 : rnd = extract_l( L_mac0( 13849, rnd, 31821 ) ); // Q0
2348 0 : y = L_mult( tilt, rnd ); // 15Q16
2349 :
2350 0 : nrgNoiseInLastFrame = L_add( nrgNoiseInLastFrame, Mpy_32_16_1( L_msu( 0, x, fac ), x ) ); // Q(31 - hTonalMDCTConc->lastBlockData.spectralData_exp * 2 - ld)
2351 0 : x = round_fx( y ); // Q15
2352 0 : nrgWhiteNoise = L_add( nrgWhiteNoise, Mpy_32_16_1( L_msu( 0, x, fac ), x ) ); // Q(1-ld)
2353 :
2354 0 : mdctSpectrum[l] = y; /* 15Q16 L_deposit_l(y);*/
2355 0 : move32();
2356 :
2357 0 : tilt = mult_r( tilt, tiltFactor ); // Q15
2358 : }
2359 :
2360 0 : IF( nrgNoiseInLastFrame == 0 )
2361 : {
2362 0 : set32_fx( mdctSpectrum, 0, crossOverFreq );
2363 0 : *mdctSpectrum_exp = SPEC_EXP_DEC;
2364 0 : move16();
2365 : }
2366 : ELSE
2367 : {
2368 0 : exp_last = add( ld, shl( hTonalMDCTConc->lastBlockData.spectralData_exp, 1 ) );
2369 0 : exp_noise = add( ld, shl( 15, 1 ) );
2370 :
2371 0 : ld = norm_l( nrgNoiseInLastFrame );
2372 0 : nrgNoiseInLastFrame = L_shl( nrgNoiseInLastFrame, ld ); // Q31 - exp_last + ld
2373 0 : exp_last = sub( exp_last, ld );
2374 0 : ld = norm_l( nrgWhiteNoise );
2375 0 : nrgWhiteNoise = L_shl( nrgWhiteNoise, ld ); // Q31 - exp_last + ld
2376 0 : exp_noise = sub( exp_noise, ld );
2377 :
2378 0 : exp = sub( exp_last, exp_noise );
2379 :
2380 0 : IF( GT_32( nrgNoiseInLastFrame, nrgWhiteNoise ) )
2381 : {
2382 0 : nrgNoiseInLastFrame = L_shr( nrgNoiseInLastFrame, 1 ); // Q31 - exp -1
2383 0 : exp = add( exp, 1 );
2384 : }
2385 0 : tmp = div_l( nrgNoiseInLastFrame, round_fx( nrgWhiteNoise ) );
2386 0 : tmp = Sqrt16( tmp, &exp );
2387 0 : g = mult_r( g, tmp );
2388 :
2389 0 : L_tmp = L_deposit_h( 0 );
2390 0 : ld = sub( hTonalMDCTConc->lastBlockData.spectralData_exp, 15 );
2391 0 : exp = sub( ld, exp );
2392 0 : IF( exp > 0 )
2393 : {
2394 0 : g = shr( g, exp );
2395 0 : *mdctSpectrum_exp = hTonalMDCTConc->lastBlockData.spectralData_exp;
2396 0 : move16();
2397 : }
2398 : ELSE
2399 : {
2400 0 : crossfadeGain = shl( crossfadeGain, exp );
2401 0 : *mdctSpectrum_exp = sub( hTonalMDCTConc->lastBlockData.spectralData_exp, exp );
2402 : }
2403 : /*make a headroom for mdct_shaping*/
2404 0 : exp = sub( *mdctSpectrum_exp, SPEC_EXP_DEC );
2405 :
2406 :
2407 0 : IF( exp < 0 )
2408 : {
2409 0 : *mdctSpectrum_exp = SPEC_EXP_DEC;
2410 0 : move16();
2411 : }
2412 : ELSE
2413 : {
2414 0 : exp = 0;
2415 0 : move16();
2416 : }
2417 :
2418 0 : FOR( l = 0; l < hTonalMDCTConc->pTCI->lowerIndex[0]; l++ )
2419 : {
2420 0 : Word16 const x = hTonalMDCTConc->lastBlockData.spectralData[l]; // Q15 - spectralData_exp
2421 0 : move16();
2422 0 : Word32 const y = mdctSpectrum[l]; // Q31-mdctSpectrum_exp
2423 0 : move32();
2424 :
2425 0 : if ( g > 0 )
2426 : {
2427 0 : L_tmp = Mpy_32_16_1( y, g ); // Q31-mdctSpectrum_exp- spectralData_exp
2428 : }
2429 :
2430 0 : L_tmp2 = L_msu( L_tmp, crossfadeGain, x ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp
2431 0 : if ( y > 0 )
2432 : {
2433 0 : L_tmp2 = L_mac( L_tmp, crossfadeGain, x ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp
2434 : }
2435 0 : mdctSpectrum[l] = L_shl( L_tmp2, exp ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp + exp
2436 0 : move32();
2437 : }
2438 :
2439 0 : FOR( i = 1; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
2440 : {
2441 0 : FOR( l = hTonalMDCTConc->pTCI->upperIndex[i - 1] + 1; l < hTonalMDCTConc->pTCI->lowerIndex[i]; l++ )
2442 : {
2443 0 : Word16 const x = hTonalMDCTConc->lastBlockData.spectralData[l]; // Q15 - spectralData_exp
2444 0 : move16();
2445 0 : Word32 const y = mdctSpectrum[l]; // Q31-mdctSpectrum_exp
2446 0 : move32();
2447 :
2448 0 : if ( g > 0 )
2449 : {
2450 0 : L_tmp = Mpy_32_16_1( y, g ); // Q31-mdctSpectrum_exp- spectralData_exp
2451 : }
2452 :
2453 0 : L_tmp2 = L_msu( L_tmp, crossfadeGain, x ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp
2454 0 : if ( y > 0 )
2455 : {
2456 0 : L_tmp2 = L_mac( L_tmp, crossfadeGain, x ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp
2457 : }
2458 0 : mdctSpectrum[l] = L_shl( L_tmp2, exp ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp + exp
2459 0 : move32();
2460 : }
2461 : }
2462 :
2463 : /* initialize bins of tonal components with zero: basically not
2464 : necessary, but currently the whole spectrum is rescaled in
2465 : mdct_noiseShaping() and then there would be a processing of
2466 : uninitialized values */
2467 0 : FOR( i = 0; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
2468 : {
2469 0 : FOR( l = hTonalMDCTConc->pTCI->lowerIndex[i]; l <= hTonalMDCTConc->pTCI->upperIndex[i]; l++ )
2470 : {
2471 0 : mdctSpectrum[l] = L_deposit_l( 0 );
2472 0 : move32();
2473 : }
2474 : }
2475 :
2476 0 : FOR( l = add( hTonalMDCTConc->pTCI->upperIndex[hTonalMDCTConc->pTCI->numIndexes - 1], 1 ); l < crossOverFreq; l++ )
2477 : {
2478 0 : Word16 const x = hTonalMDCTConc->lastBlockData.spectralData[l]; // Q15 - spectralData_exp
2479 0 : move16();
2480 0 : Word32 const y = mdctSpectrum[l]; // Q31-mdctSpectrum_exp
2481 0 : move32();
2482 :
2483 0 : if ( g > 0 )
2484 : {
2485 0 : L_tmp = Mpy_32_16_1( y, g ); // Q31-mdctSpectrum_exp- spectralData_exp
2486 : }
2487 :
2488 0 : L_tmp2 = L_msu( L_tmp, crossfadeGain, x ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp
2489 0 : if ( y > 0 )
2490 : {
2491 0 : L_tmp2 = L_mac( L_tmp, crossfadeGain, x ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp
2492 : }
2493 0 : mdctSpectrum[l] = L_shl( L_tmp2, exp ); // Q15 - e_crossfadeGain + Q15 - spectralData_exp + exp
2494 0 : move32();
2495 : }
2496 : }
2497 0 : exp = sub( hTonalMDCTConc->lastBlockData.spectralData_exp, sub( *mdctSpectrum_exp, 16 ) );
2498 0 : FOR( l = crossOverFreq; l < hTonalMDCTConc->lastBlockData.nSamples; l++ )
2499 : {
2500 0 : mdctSpectrum[l] = L_shl( L_deposit_l( hTonalMDCTConc->lastBlockData.spectralData[l] ), exp ); // Q15 - spectralData_exp + exp
2501 0 : move32();
2502 : }
2503 : }
2504 : }
2505 :
2506 0 : *pSeed = rnd;
2507 0 : move16();
2508 :
2509 0 : return;
2510 : }
2511 :
2512 0 : void TonalMDCTConceal_Apply(
2513 : const TonalMDCTConcealPtr hTonalMDCTConc, /*IN */
2514 : Word32 *mdctSpectrum, // Q31-*mdctSpectrum_exp /*IN/OUT*/
2515 : Word16 *mdctSpectrum_exp /*IN */
2516 : )
2517 : {
2518 : Word16 i, l, exp;
2519 : Word16 *phaseDiff, *pCurrentPhase;
2520 : Word32 phaseToAdd, currentPhase;
2521 : Word32 powerSpectrum[L_FRAME_MAX];
2522 : Word16 nSamples;
2523 :
2524 :
2525 0 : IF( s_and( hTonalMDCTConc->lastBlockData.blockIsValid, hTonalMDCTConc->secondLastBlockData.blockIsValid ) )
2526 : {
2527 0 : assert( hTonalMDCTConc->pTCI->numIndexes > 0 );
2528 :
2529 0 : nSamples = hTonalMDCTConc->nNonZeroSamples;
2530 0 : move16();
2531 0 : assert( hTonalMDCTConc->pTCI->upperIndex[hTonalMDCTConc->pTCI->numIndexes - 1] < nSamples );
2532 :
2533 : {
2534 :
2535 0 : mdct_shaping_16( hTonalMDCTConc->secondLastPowerSpectrum, hTonalMDCTConc->nSamplesCore, nSamples,
2536 0 : hTonalMDCTConc->secondLastBlockData.scaleFactors, hTonalMDCTConc->secondLastBlockData.scaleFactors_exp,
2537 0 : hTonalMDCTConc->secondLastBlockData.scaleFactors_max_e, powerSpectrum );
2538 : }
2539 0 : phaseDiff = hTonalMDCTConc->pTCI->phaseDiff; /* if multiple frame loss occurs use the phase from the last frame and continue rotating */
2540 0 : pCurrentPhase = hTonalMDCTConc->pTCI->phase_currentFramePredicted;
2541 :
2542 0 : exp = sub( *mdctSpectrum_exp, add( add( hTonalMDCTConc->secondLastPowerSpectrum_exp, add( hTonalMDCTConc->secondLastBlockData.gain_tcx_exp, 1 ) ), hTonalMDCTConc->secondLastBlockData.scaleFactors_max_e ) );
2543 :
2544 0 : IF( !hTonalMDCTConc->lastBlockData.blockIsConcealed )
2545 : {
2546 0 : if ( hTonalMDCTConc->secondLastBlockData.tonalConcealmentActive != 0 )
2547 : {
2548 0 : hTonalMDCTConc->nFramesLost = add( hTonalMDCTConc->nFramesLost, 2 ); /*Q1*/
2549 0 : move16();
2550 : }
2551 0 : if ( hTonalMDCTConc->secondLastBlockData.tonalConcealmentActive == 0 )
2552 : {
2553 0 : hTonalMDCTConc->nFramesLost = 3; /*Q1*/
2554 0 : move16();
2555 : }
2556 : }
2557 : /* for each index group */
2558 0 : FOR( i = 0; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
2559 : {
2560 : /*phaseToAdd = hTonalMDCTConc->nFramesLost*phaseDiff[i]; */
2561 0 : phaseToAdd = L_mult0( hTonalMDCTConc->nFramesLost, phaseDiff[i] ); /*Q1*3Q12=2Q13*/
2562 : /* Move phaseToAdd to range -PI..PI */
2563 :
2564 0 : WHILE( GT_32( phaseToAdd, 25736l /*EVS_PI Q13*/ ) )
2565 : {
2566 0 : phaseToAdd = L_sub( phaseToAdd, 51472l /*2*EVS_PI Q13*/ );
2567 : }
2568 0 : WHILE( LT_32( phaseToAdd, -25736l /*-EVS_PI Q13*/ ) )
2569 : {
2570 0 : phaseToAdd = L_add( phaseToAdd, 51472l /*2*EVS_PI Q13*/ );
2571 : }
2572 :
2573 0 : FOR( l = hTonalMDCTConc->pTCI->lowerIndex[i]; l <= hTonalMDCTConc->pTCI->upperIndex[i]; l++ )
2574 : {
2575 : /* *pCurrentPhase and phaseToAdd are in range -PI..PI */
2576 0 : currentPhase = L_mac0( phaseToAdd, ( *pCurrentPhase++ ), 1 ); /*2Q13+2Q13=3Q13*/
2577 :
2578 0 : if ( GT_32( currentPhase, 25736l /*EVS_PI Q13*/ ) )
2579 : {
2580 0 : currentPhase = L_sub( currentPhase, 51472l /*2*EVS_PI Q13*/ );
2581 : }
2582 0 : if ( LT_32( currentPhase, -25736l /*-EVS_PI Q13*/ ) )
2583 : {
2584 0 : currentPhase = L_add( currentPhase, 51472l /*2*EVS_PI Q13*/ );
2585 : }
2586 : /* getCosWord16 returns 1Q14*/
2587 0 : mdctSpectrum[l] = Mpy_32_16_1( powerSpectrum[l], getCosWord16( extract_l( currentPhase ) ) );
2588 0 : move32();
2589 0 : mdctSpectrum[l] = L_shr( mdctSpectrum[l], exp );
2590 0 : move32();
2591 : }
2592 : }
2593 : }
2594 :
2595 0 : hTonalMDCTConc->nFramesLost = add( hTonalMDCTConc->nFramesLost, 2 ); /*Q1*/
2596 0 : move16();
2597 :
2598 0 : return;
2599 : }
2600 :
2601 477 : void TonalMDCTConceal_Apply_ivas_fx(
2602 : TonalMDCTConcealPtr hTonalMDCTConc, /*IN */
2603 : Word32 *mdctSpectrum, // Q31-*mdctSpectrum_exp /*IN/OUT*/
2604 : Word16 mdctSpectrum_exp, /*IN */
2605 : const PsychoacousticParameters *psychParamsCurrent )
2606 :
2607 : {
2608 : Word16 i, l;
2609 : Word16 *phaseDiff, *pCurrentPhase;
2610 : Word32 phaseToAdd;
2611 : Word32 powerSpectrum[L_FRAME_MAX];
2612 : Word16 powerSpectrum_exp;
2613 : Word32 scaleFactors[FDNS_NPTS];
2614 : Word16 nSamples;
2615 : Word16 nBands;
2616 :
2617 477 : Word16 *tmp_secondLastPowerSpectrum = hTonalMDCTConc->secondLastPowerSpectrum;
2618 477 : Word16 tmp_secondLastPowerSpectrum_exp = hTonalMDCTConc->secondLastPowerSpectrum_exp;
2619 477 : move16();
2620 :
2621 477 : Word16 max_nSamples = s_max( hTonalMDCTConc->nNonZeroSamples, hTonalMDCTConc->nSamplesCore );
2622 :
2623 : // To avoid garbage values
2624 477 : set32_fx( powerSpectrum, 0, L_FRAME_MAX );
2625 :
2626 : /* Creating 32-bit scaleFactors with common exponent. */
2627 31005 : FOR( i = 0; i < FDNS_NPTS; i++ )
2628 : {
2629 30528 : scaleFactors[i] = L_shr( L_deposit_h( hTonalMDCTConc->secondLastBlockData.scaleFactors[i] ), sub( hTonalMDCTConc->secondLastBlockData.scaleFactors_max_e, hTonalMDCTConc->secondLastBlockData.scaleFactors_exp[i] ) ); // Q31- scaleFactors_max_e+scaleFactors_exp[i]
2630 30528 : move32();
2631 : }
2632 :
2633 477 : IF( s_and( hTonalMDCTConc->lastBlockData.blockIsValid, hTonalMDCTConc->secondLastBlockData.blockIsValid ) )
2634 : {
2635 477 : assert( hTonalMDCTConc->pTCI->numIndexes > 0 );
2636 :
2637 477 : nSamples = hTonalMDCTConc->nNonZeroSamples;
2638 477 : move16();
2639 477 : assert( hTonalMDCTConc->pTCI->upperIndex[hTonalMDCTConc->pTCI->numIndexes - 1] < nSamples );
2640 :
2641 259744 : FOR( i = 0; i < nSamples; i++ )
2642 : {
2643 259267 : powerSpectrum[i] = L_deposit_h( tmp_secondLastPowerSpectrum[i] ); // Q31 - secondLastPowerSpectrum_exp
2644 259267 : move16();
2645 : }
2646 477 : powerSpectrum_exp = tmp_secondLastPowerSpectrum_exp;
2647 477 : move16();
2648 :
2649 477 : Word16 exp1 = powerSpectrum_exp;
2650 477 : move16();
2651 :
2652 477 : IF( psychParamsCurrent == NULL )
2653 : {
2654 192 : nBands = FDNS_NPTS;
2655 192 : move16();
2656 192 : mdct_noiseShaping_ivas_fx( powerSpectrum, &powerSpectrum_exp, hTonalMDCTConc->nSamplesCore, hTonalMDCTConc->secondLastBlockData.scaleFactors,
2657 192 : hTonalMDCTConc->secondLastBlockData.scaleFactors_exp );
2658 : }
2659 : ELSE
2660 : {
2661 : Word16 q_ps, q_sf;
2662 285 : q_ps = sub( 31, powerSpectrum_exp );
2663 285 : q_sf = sub( 31, hTonalMDCTConc->secondLastBlockData.scaleFactors_max_e );
2664 :
2665 : /* adding guard bit */
2666 285 : q_ps = sub( q_ps, 1 );
2667 159261 : FOR( Word16 c = 0; c < hTonalMDCTConc->nSamplesCore; c++ )
2668 : {
2669 158976 : powerSpectrum[c] = L_shr( powerSpectrum[c], 1 ); // q_ps -1
2670 158976 : move32();
2671 : }
2672 :
2673 : /* adding guard bit */
2674 285 : q_sf = sub( q_sf, 1 );
2675 18525 : FOR( Word16 c = 0; c < FDNS_NPTS; c++ )
2676 : {
2677 18240 : scaleFactors[c] = L_shr( scaleFactors[c], 1 ); // q_sf - 1
2678 18240 : move32();
2679 : }
2680 :
2681 285 : sns_shape_spectrum_fx( powerSpectrum, &q_ps, psychParamsCurrent, scaleFactors, q_sf, hTonalMDCTConc->nSamplesCore, NULL );
2682 :
2683 285 : powerSpectrum_exp = sub( 31, add( q_ps, 1 ) );
2684 :
2685 285 : nBands = psychParamsCurrent->nBands;
2686 285 : move16();
2687 : }
2688 :
2689 477 : Word16 exp_left = powerSpectrum_exp;
2690 477 : move16();
2691 477 : Word16 exp_right = exp1;
2692 477 : move16();
2693 :
2694 50786 : FOR( Word16 c = hTonalMDCTConc->nSamplesCore; c < nSamples; c++ )
2695 : {
2696 50309 : powerSpectrum[c] = Mpy_32_16_1( powerSpectrum[c], hTonalMDCTConc->secondLastBlockData.scaleFactors[nBands - 1] ); // Q31 -(exp_right + scaleFactors_exp[])
2697 50309 : move32();
2698 : }
2699 477 : exp_right = add( exp_right, hTonalMDCTConc->secondLastBlockData.scaleFactors_exp[nBands - 1] );
2700 :
2701 477 : Word16 max_e = s_max( exp_right, exp_left );
2702 272546 : FOR( Word16 c = 0; c < max_nSamples; c++ )
2703 : {
2704 272069 : test();
2705 272069 : test();
2706 272069 : test();
2707 272069 : test();
2708 272069 : IF( GE_16( c, hTonalMDCTConc->nSamplesCore ) && LT_16( c, nSamples ) && GT_16( max_e, exp_right ) )
2709 : {
2710 38464 : powerSpectrum[c] = L_shr( powerSpectrum[c], sub( max_e, exp_right ) ); // Q31-max_e
2711 38464 : move32();
2712 : }
2713 233605 : ELSE IF( ( LT_16( c, hTonalMDCTConc->nSamplesCore ) || GT_16( c, nSamples ) ) && GT_16( max_e, exp_left ) )
2714 : {
2715 30400 : powerSpectrum[c] = L_shr( powerSpectrum[c], sub( max_e, exp_left ) ); // Q31-max_e
2716 30400 : move32();
2717 : }
2718 : }
2719 477 : powerSpectrum_exp = max_e;
2720 477 : move16();
2721 :
2722 477 : phaseDiff = hTonalMDCTConc->pTCI->phaseDiff; /* if multiple frame loss occurs use the phase from the last frame and continue rotating */
2723 477 : pCurrentPhase = hTonalMDCTConc->pTCI->phase_currentFramePredicted;
2724 :
2725 477 : IF( !hTonalMDCTConc->lastBlockData.blockIsConcealed )
2726 : {
2727 369 : if ( hTonalMDCTConc->secondLastBlockData.tonalConcealmentActive != 0 )
2728 : {
2729 0 : hTonalMDCTConc->nFramesLost = add( hTonalMDCTConc->nFramesLost, 2 ); /*Q1*/
2730 0 : move16();
2731 : }
2732 369 : if ( hTonalMDCTConc->secondLastBlockData.tonalConcealmentActive == 0 )
2733 : {
2734 369 : hTonalMDCTConc->nFramesLost = 3; /*Q1*/
2735 369 : move16();
2736 : }
2737 : }
2738 :
2739 : /* for each index group */
2740 3024 : FOR( i = 0; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
2741 : {
2742 2547 : phaseToAdd = L_mult0( hTonalMDCTConc->nFramesLost, phaseDiff[i] ); /*Q1*3Q12=2Q13*/
2743 :
2744 : /* Move phaseToAdd to range -PI..PI */
2745 3417 : WHILE( GT_32( phaseToAdd, 25736l /*EVS_PI Q13*/ ) )
2746 : {
2747 870 : phaseToAdd = L_sub( phaseToAdd, 51472l /*2*EVS_PI Q13*/ );
2748 : }
2749 4228 : WHILE( LT_32( phaseToAdd, -25736l /*-EVS_PI Q13*/ ) )
2750 : {
2751 1681 : phaseToAdd = L_add( phaseToAdd, 51472l /*2*EVS_PI Q13*/ );
2752 : }
2753 :
2754 20337 : FOR( l = hTonalMDCTConc->pTCI->lowerIndex[i]; l <= hTonalMDCTConc->pTCI->upperIndex[i]; l++ )
2755 : {
2756 : /* *pCurrentPhase and phaseToAdd are in range -PI..PI */
2757 17790 : Word32 currentPhase = L_mac0( phaseToAdd, ( *pCurrentPhase++ ), 1 ); /*2Q13+2Q13=3Q13*/
2758 17790 : IF( GT_32( currentPhase, 25736l /*EVS_PI Q13*/ ) )
2759 : {
2760 1935 : currentPhase = L_sub( currentPhase, 51472l /*2*EVS_PI Q13*/ );
2761 : }
2762 17790 : IF( LT_32( currentPhase, -25736l /*-EVS_PI Q13*/ ) )
2763 : {
2764 2657 : currentPhase = L_add( currentPhase, 51472l /*2*EVS_PI Q13*/ );
2765 : }
2766 :
2767 : /* getCosWord16 returns 1Q14*/
2768 17790 : mdctSpectrum[l] = Mpy_32_16_1( powerSpectrum[l], getCosWord16( extract_l( currentPhase ) ) );
2769 17790 : move32();
2770 17790 : mdctSpectrum[l] = L_shr( mdctSpectrum[l], sub( mdctSpectrum_exp, add( powerSpectrum_exp, 1 ) ) );
2771 : }
2772 : }
2773 : }
2774 :
2775 477 : hTonalMDCTConc->nFramesLost = add( hTonalMDCTConc->nFramesLost, 2 ); /*Q1*/
2776 477 : move16();
2777 :
2778 477 : return;
2779 : }
2780 :
2781 646 : void TonalMDCTConceal_SaveTimeSignal(
2782 : TonalMDCTConcealPtr hTonalMDCTConc,
2783 : Word16 *timeSignal, // Qx
2784 : Word16 nNewSamples
2785 :
2786 : )
2787 : {
2788 646 : IF( EQ_16( nNewSamples, hTonalMDCTConc->nSamples ) )
2789 : {
2790 646 : assert( nNewSamples <= L_FRAME_MAX );
2791 646 : IF( !hTonalMDCTConc->secondLastBlockData.tonalConcealmentActive )
2792 : {
2793 646 : Copy( hTonalMDCTConc->lastPcmOut + hTonalMDCTConc->nSamples / 2, hTonalMDCTConc->secondLastPcmOut, hTonalMDCTConc->nSamples / 2 );
2794 : }
2795 646 : Copy( timeSignal, hTonalMDCTConc->lastPcmOut, hTonalMDCTConc->nSamples );
2796 : }
2797 :
2798 646 : return;
2799 : }
2800 891572 : void TonalMDCTConceal_SaveTimeSignal_ivas_fx(
2801 : TonalMDCTConcealPtr hTonalMDCTConc,
2802 : Word16 *timeSignal, // q_timeSignal
2803 : Word16 q_timeSignal,
2804 : Word16 nNewSamples )
2805 : {
2806 891572 : IF( EQ_16( nNewSamples, hTonalMDCTConc->nSamples ) )
2807 : {
2808 876042 : assert( nNewSamples <= L_FRAME_MAX );
2809 876042 : IF( !hTonalMDCTConc->secondLastBlockData.tonalConcealmentActive )
2810 : {
2811 : Word16 exp, len;
2812 875682 : len = shr( hTonalMDCTConc->nSamples, 1 );
2813 875682 : Copy( hTonalMDCTConc->lastPcmOut + len, hTonalMDCTConc->secondLastPcmOut, len );
2814 875682 : exp = sub( q_timeSignal, hTonalMDCTConc->q_lastPcmOut );
2815 875682 : IF( exp != 0 )
2816 : {
2817 136491 : Scale_sig( hTonalMDCTConc->secondLastPcmOut, len, exp ); // q_timeSignal
2818 : }
2819 : }
2820 876042 : Copy( timeSignal, hTonalMDCTConc->lastPcmOut, hTonalMDCTConc->nSamples );
2821 876042 : hTonalMDCTConc->q_lastPcmOut = q_timeSignal;
2822 876042 : move16();
2823 : }
2824 :
2825 891572 : return;
2826 : }
2827 1497 : static void CalcPowerSpec(
2828 : const Word32 *mdctSpec, /* i: MDCT spectrum Q31-mdctSpec_exp */
2829 : const Word16 mdctSpec_exp, /* i: exponent of MDCT spectrum */
2830 : const Word32 *mdstSpec, /* i: MDST spectrum Q31-mdstSpec_exp */
2831 : const Word16 mdstSpec_exp, /* i: exponent of MDST spectrum */
2832 : const Word16 nSamples, /* i: frame size */
2833 : const Word16 floorPowerSpectrum, /* i: lower limit for power spectrum bins Q0 */
2834 : Word32 *powerSpec, /* o: power spectrum Q31- powerSpec_exp */
2835 : Word16 *powerSpec_exp ) /* o: exponent of power spectrum */
2836 : {
2837 : Word16 k, s1, s2, tmp;
2838 : Word32 x, L_tmp, L_tmp_floor;
2839 :
2840 :
2841 1497 : k = s_max( mdctSpec_exp, mdstSpec_exp );
2842 1497 : *powerSpec_exp = add( add( k, k ), 3 ); /*extra 3 bits of headroom for MA filter in getEnvelope*/
2843 1497 : move16();
2844 1497 : s1 = sub( *powerSpec_exp, add( mdctSpec_exp, mdctSpec_exp ) );
2845 1497 : s2 = sub( *powerSpec_exp, add( mdstSpec_exp, mdstSpec_exp ) );
2846 :
2847 1497 : k = sub( 31, *powerSpec_exp );
2848 : /* If the signal is bellow floor, special care is needed for *powerSpec_exp */
2849 1497 : IF( LT_16( add( 16 - 3, norm_s( floorPowerSpectrum ) ), k ) ) /*extra 3 bits of headroom for MA filter in getEnvelope*/
2850 : {
2851 90 : k = sub( k, add( 16 - 3, norm_s( floorPowerSpectrum ) ) ); /*extra 3 bits of headroom for MA filter in getEnvelope*/
2852 90 : *powerSpec_exp = add( *powerSpec_exp, k );
2853 90 : s1 = add( s1, k );
2854 90 : s2 = add( s2, k );
2855 90 : k = add( 16 - 3, norm_s( floorPowerSpectrum ) );
2856 : }
2857 1497 : L_tmp_floor = L_shl( L_deposit_l( floorPowerSpectrum ), k );
2858 :
2859 1497 : tmp = sub( nSamples, 2 );
2860 778164 : FOR( k = 1; k <= tmp; k++ )
2861 : {
2862 776667 : x = Mpy_32_32( mdctSpec[k], mdctSpec[k] ); /*Q31,2*mdctSpec_exp*/
2863 :
2864 776667 : L_tmp = Mpy_32_32( mdstSpec[k], mdstSpec[k] ); /*Q31,2*mdstSpec_exp*/
2865 776667 : x = L_add( L_shr( x, s1 ), L_shr( L_tmp, s2 ) ); /*Q31,*powerSpec_exp*/
2866 :
2867 776667 : powerSpec[k] = L_max( L_tmp_floor, x );
2868 776667 : move32();
2869 : }
2870 :
2871 1497 : powerSpec[0] = L_shr( powerSpec[1], 1 );
2872 1497 : move32();
2873 1497 : powerSpec[nSamples - 1] = L_shr( powerSpec[nSamples - 2], 1 );
2874 1497 : move32();
2875 1497 : }
2876 :
2877 :
2878 : /*******************************************************/
2879 : /*-------------- public functions -------------------- */
2880 : /*******************************************************/
2881 :
2882 3108 : void TonalMdctConceal_create_concealment_noise_ivas_fx(
2883 : Word32 concealment_noise[L_FRAME48k], // Q31-concealment_noise_exp
2884 : Word16 *concealment_noise_exp,
2885 : CPE_DEC_HANDLE hCPE,
2886 : const Word16 L_frameTCX, // Q0
2887 : const Word16 L_frame, // Q0
2888 : const Word16 idchan, // Q0
2889 : const Word16 subframe_idx, // Q0
2890 : const Word16 core, // Q0
2891 : const Word16 crossfade_gain, // Q15
2892 : const TONALMDCTCONC_NOISE_GEN_MODE noise_gen_mode )
2893 : {
2894 : STEREO_MDCT_DEC_DATA_HANDLE hStereoMdct;
2895 : TonalMDCTConcealPtr hTonalMDCTConc;
2896 : Decoder_State *st;
2897 : HANDLE_FD_CNG_COM hFdCngCom;
2898 : Word16 *rnd_c, *rnd;
2899 : Word16 crossOverFreq, i, save_rnd_c, max_noise_line;
2900 : Word16 c, c_inv, inc, inc_log2;
2901 : Word32 noise_shape_buffer[L_FRAME48k];
2902 : Word16 noise_shape_buffer_e[L_FRAME48k];
2903 3108 : Word16 start_idx, stop_idx, noise_shape_buffer_common_exp = MIN16B_FLT_FX, last_scf_e, temp_e;
2904 3108 : move16();
2905 : Word32 *cngNoiseLevelPtr;
2906 : Word32 last_scf;
2907 :
2908 : Word16 c_e, c_inv_e;
2909 :
2910 3108 : push_wmops( "create_conc_noise" );
2911 :
2912 3108 : hStereoMdct = hCPE->hStereoMdct;
2913 3108 : st = hCPE->hCoreCoder[idchan];
2914 3108 : hTonalMDCTConc = st->hTonalMDCTConc;
2915 3108 : hFdCngCom = st->hFdCngDec->hFdCngCom;
2916 3108 : rnd = &hStereoMdct->noise_seeds_channels[idchan];
2917 3108 : rnd_c = &hStereoMdct->noise_seed_common;
2918 :
2919 : /* determine start bin for IGF */
2920 3108 : IF( st->igf == 0 )
2921 : {
2922 1096 : IF( st->narrowBand == 0 )
2923 : {
2924 : /* minimum needed for output with sampling rates lower then the
2925 : nominal sampling rate */
2926 1096 : crossOverFreq = s_min( L_frameTCX, L_frame );
2927 : }
2928 : ELSE
2929 : {
2930 0 : crossOverFreq = L_frameTCX;
2931 0 : move16();
2932 : }
2933 : }
2934 : ELSE
2935 : {
2936 2012 : crossOverFreq = s_min( st->hIGFDec->infoIGFStartLine, L_frameTCX );
2937 : }
2938 :
2939 : /* for tonal mdct concealment with tonal components above the crossover frequency, conditionally raise the frequency index until which noise is generated */
2940 3108 : max_noise_line = crossOverFreq;
2941 3108 : move16();
2942 3108 : IF( st->tonal_mdct_plc_active )
2943 : {
2944 95 : max_noise_line = s_max( max_noise_line, extract_l( L_add( hTonalMDCTConc->pTCI->upperIndex[hTonalMDCTConc->pTCI->numIndexes - 1], 1 ) ) );
2945 : }
2946 :
2947 : /* first lost frame is handled separately */
2948 3108 : IF( !hTonalMDCTConc->lastBlockData.blockIsConcealed )
2949 : {
2950 1566 : *rnd = add( 1977, idchan ); // Q0
2951 1566 : move16();
2952 : /* will be set twice when looping over two channels, but does not matter */
2953 1566 : *rnd_c = 1979; // Q0
2954 1566 : move16();
2955 : }
2956 :
2957 3108 : IF( GT_16( crossfade_gain, 32734 ) )
2958 : /* Due to precision loss */ /* 0.999 in Q15*/
2959 : {
2960 : /* In first frame, noise is weighted with zero anyway, we only need the random numbers for the sign scrambling */
2961 611839 : FOR( i = 0; i < max_noise_line; i++ )
2962 : {
2963 610273 : *rnd = own_random( rnd );
2964 610273 : move16();
2965 610273 : concealment_noise[i] = *rnd; // Q31-concealment_noise_exp
2966 610273 : move32();
2967 : }
2968 1566 : *concealment_noise_exp = 31;
2969 1566 : move16();
2970 1566 : pop_wmops();
2971 :
2972 1566 : return;
2973 : }
2974 :
2975 1542 : save_rnd_c = *rnd_c; // Q0
2976 1542 : move16();
2977 :
2978 1542 : c_e = 1;
2979 1542 : move16();
2980 1542 : c_inv_e = 1;
2981 1542 : move16();
2982 :
2983 1542 : c = Sqrt16( hStereoMdct->lastCoh_fx, &c_e ); // Q1 = 15 - c_e
2984 1542 : c_inv = Sqrt16( sub( ONE_IN_Q14, hStereoMdct->lastCoh_fx ), &c_inv_e ); // Q2 = 15 - c_inv_e
2985 :
2986 1542 : IF( NE_16( c_e, c_inv_e ) )
2987 : {
2988 361 : IF( LT_16( c_e, c_inv_e ) )
2989 : {
2990 309 : c = shr( c, sub( c_inv_e, c_e ) ); // Q0
2991 309 : c_e = c_inv_e;
2992 309 : move16();
2993 : }
2994 : ELSE
2995 : {
2996 52 : c_inv = shr( c_inv, sub( c_e, c_inv_e ) ); // Q0
2997 : }
2998 : }
2999 :
3000 : /* pre-compute the noise shape for later weighting of the noise spectra */
3001 1542 : cngNoiseLevelPtr = &hFdCngCom->cngNoiseLevel[0];
3002 1542 : last_scf_e = hFdCngCom->cngNoiseLevelExp;
3003 1542 : move16();
3004 :
3005 1542 : IF( GT_16( st->core, TCX_20_CORE ) )
3006 : {
3007 8 : inc = 2;
3008 8 : inc_log2 = 1;
3009 8 : move16();
3010 8 : move16();
3011 8 : start_idx = shr( hFdCngCom->startBand, inc_log2 );
3012 8 : stop_idx = shr( hFdCngCom->stopFFTbin, inc_log2 );
3013 : }
3014 : ELSE
3015 : {
3016 1534 : inc = 1;
3017 1534 : start_idx = hFdCngCom->startBand;
3018 1534 : stop_idx = hFdCngCom->stopFFTbin;
3019 1534 : move16();
3020 1534 : move16();
3021 1534 : move16();
3022 : }
3023 :
3024 4618 : FOR( i = 0; i < start_idx; i++ )
3025 : {
3026 3076 : noise_shape_buffer[i] = 0;
3027 3076 : move32();
3028 3076 : noise_shape_buffer_e[i] = 0;
3029 3076 : move16();
3030 : }
3031 490626 : FOR( ; i < stop_idx; ( i++, cngNoiseLevelPtr += inc ) )
3032 : {
3033 489084 : noise_shape_buffer_e[i] = hFdCngCom->cngNoiseLevelExp;
3034 489084 : move16();
3035 489084 : noise_shape_buffer[i] = Sqrt32( *( cngNoiseLevelPtr ), &noise_shape_buffer_e[i] ); // Q31-noise_shape_buffer_e[i]
3036 489084 : move32();
3037 489084 : noise_shape_buffer_common_exp = s_max( noise_shape_buffer_e[i], noise_shape_buffer_common_exp );
3038 : }
3039 :
3040 493702 : FOR( i = 0; i < stop_idx; i++ )
3041 : {
3042 492160 : IF( NE_16( noise_shape_buffer_common_exp, noise_shape_buffer_e[i] ) )
3043 : {
3044 :
3045 42022 : noise_shape_buffer[i] = L_shr( noise_shape_buffer[i], sub( noise_shape_buffer_common_exp, noise_shape_buffer_e[i] ) ); // Q31- (noise_shape_buffer_common_exp-noise_shape_buffer_e[i])
3046 42022 : move32();
3047 : }
3048 : }
3049 :
3050 1542 : last_scf = Sqrt32( *( cngNoiseLevelPtr - inc ), &last_scf_e ); // Q31-last_scf_e
3051 :
3052 1542 : IF( LT_16( noise_shape_buffer_common_exp, last_scf_e ) )
3053 : {
3054 0 : Scale_sig32( noise_shape_buffer, stop_idx, sub( noise_shape_buffer_common_exp, last_scf_e ) ); // Q31- (noise_shape_buffer_common_exp-last_scf_e)
3055 :
3056 0 : noise_shape_buffer_common_exp = last_scf_e;
3057 0 : move16();
3058 : }
3059 : ELSE
3060 : {
3061 1542 : last_scf = L_shl( last_scf, sub( last_scf_e, noise_shape_buffer_common_exp ) ); // Q31-(last_scf_e-noise_shape_buffer_common_exp)
3062 : }
3063 :
3064 98086 : FOR( ; i < max_noise_line; i++ )
3065 : {
3066 96544 : noise_shape_buffer[i] = last_scf; // Q31 - noise_shape_buffer_common_exp
3067 96544 : move32();
3068 : }
3069 :
3070 : /* fill the noise vector */
3071 1542 : hTonalMDCTConc->curr_noise_nrg = MDCT_ST_PLC_FADEOUT_MIN_NOISE_NRG_Q31; // Q31
3072 1542 : move32();
3073 1542 : hTonalMDCTConc->curr_noise_nrg_exp = 0;
3074 1542 : move16();
3075 1542 : *concealment_noise_exp = add( 16, add( noise_shape_buffer_common_exp, c_e ) );
3076 1542 : move16();
3077 1542 : temp_e = hTonalMDCTConc->curr_noise_nrg_exp;
3078 1542 : move16();
3079 :
3080 1542 : test();
3081 1542 : test();
3082 1542 : test();
3083 1542 : test();
3084 1542 : IF( EQ_16( noise_gen_mode, EQUAL_CORES ) || ( ( EQ_16( noise_gen_mode, TCX20_IN_0_TCX10_IN_1 ) && EQ_16( idchan, 0 ) ) || ( EQ_16( noise_gen_mode, TCX10_IN_0_TCX20_IN_1 ) && EQ_16( idchan, 1 ) ) ) )
3085 : {
3086 : /* current channel is TCX20 -> generate noise for "full-length" spectrum */
3087 :
3088 590246 : FOR( i = 0; i < max_noise_line; i++ )
3089 : {
3090 588704 : *rnd = own_random( rnd ); // Q0
3091 588704 : *rnd_c = own_random( rnd_c );
3092 :
3093 588704 : move16();
3094 588704 : move16();
3095 :
3096 588704 : concealment_noise[i] = Mpy_32_32( L_add( L_shr( L_mult( c_inv, *rnd ), 1 ), L_shr( L_mult( c, *rnd_c ), 1 ) ), noise_shape_buffer[i] ); // Q31 - *concealment_noise_exp
3097 588704 : move32();
3098 588704 : IF( concealment_noise[i] != 0 )
3099 : {
3100 58234 : hTonalMDCTConc->curr_noise_nrg = BASOP_Util_Add_Mant32Exp( hTonalMDCTConc->curr_noise_nrg, hTonalMDCTConc->curr_noise_nrg_exp, Mpy_32_32( concealment_noise[i], concealment_noise[i] ), shl( *concealment_noise_exp, 1 ), &temp_e ); // Q31-temp_e
3101 : }
3102 588704 : hTonalMDCTConc->curr_noise_nrg_exp = temp_e;
3103 588704 : move16();
3104 : }
3105 : }
3106 : ELSE /* ( ( noise_gen_mode == TCX10_IN_0_TCX20_IN_1 && idchan == 0 ) || ( noise_gen_mode == TCX20_IN_0_TCX10_IN_1 && idchan == 1 ) ) */
3107 : {
3108 : /* current channel is TCX10 and the other is TCX20 -> generate noise for "half-length" spectrum, but "increment" mid seed twice, to have the same seed in mid as the other (TCX20) channel for next frame */
3109 0 : FOR( i = 0; i < max_noise_line; i++ )
3110 : {
3111 0 : *rnd = own_random( rnd ); // Q0
3112 0 : *rnd_c = own_random( rnd_c ); // Q0
3113 0 : move16();
3114 0 : move16();
3115 :
3116 0 : concealment_noise[i] = Mpy_32_32( L_add( L_shr( L_mult( c_inv, *rnd ), 1 ), L_shr( L_mult( c, *rnd_c ), 1 ) ), noise_shape_buffer[i] );
3117 0 : move32();
3118 0 : IF( concealment_noise[i] != 0 )
3119 : {
3120 0 : hTonalMDCTConc->curr_noise_nrg = BASOP_Util_Add_Mant32Exp( hTonalMDCTConc->curr_noise_nrg, hTonalMDCTConc->curr_noise_nrg_exp, Mpy_32_32( concealment_noise[i], concealment_noise[i] ), shl( *concealment_noise_exp, 1 ), &temp_e ); // Q31-temp_e
3121 : }
3122 0 : hTonalMDCTConc->curr_noise_nrg_exp = temp_e;
3123 0 : move16();
3124 :
3125 0 : *rnd_c = own_random( rnd_c );
3126 0 : move16();
3127 : }
3128 : }
3129 :
3130 1542 : IF( st->tonal_mdct_plc_active )
3131 : {
3132 13 : FOR( i = crossOverFreq; i < s_max( crossOverFreq, hTonalMDCTConc->pTCI->lowerIndex[hTonalMDCTConc->pTCI->numIndexes - 1] ); ++i )
3133 : {
3134 0 : concealment_noise[i] = 0;
3135 0 : move32();
3136 : }
3137 : }
3138 :
3139 : /* restore common seed
3140 : - after finishing the first channel
3141 : - after a first subframe if the current channel is TCX10 */
3142 :
3143 1542 : test();
3144 1542 : test();
3145 1542 : test();
3146 1542 : test();
3147 1542 : test();
3148 1542 : IF( ( EQ_16( idchan, 0 ) && ( EQ_16( core, TCX_20 ) || ( EQ_16( core, TCX_10 ) && EQ_16( subframe_idx, 1 ) ) ) ) || ( EQ_16( core, TCX_10 ) && EQ_16( subframe_idx, 0 ) ) )
3149 : {
3150 761 : *rnd_c = save_rnd_c;
3151 761 : move16();
3152 : }
3153 :
3154 1542 : st->seed_tcx_plc = *rnd;
3155 1542 : move16();
3156 :
3157 1542 : pop_wmops();
3158 :
3159 1542 : return;
3160 : }
3161 :
3162 :
3163 1803 : void TonalMdctConceal_whiten_noise_shape_ivas_fx(
3164 : Decoder_State *st,
3165 : const Word16 L_frame,
3166 : const TONALMDCTCONC_NOISE_SHAPE_WHITENING_MODE whitening_mode )
3167 : {
3168 : Word16 inc, start_idx, stop_idx, i;
3169 : Word32 *noiseLevelPtr, *scfs_bg, *scfs_for_shaping;
3170 : Word16 noiseLevelPtr_exp;
3171 : HANDLE_FD_CNG_COM hFdCngCom;
3172 : Word32 whitenend_noise_shape[L_FRAME16k];
3173 : Word16 q_wns;
3174 : Word32 scfs_int[FDNS_NPTS];
3175 : const PsychoacousticParameters *psychParams;
3176 :
3177 1803 : push_wmops( "apply_sns_on_noise_shape" );
3178 :
3179 1803 : scfs_bg = &st->hTonalMDCTConc->scaleFactorsBackground_fx[0];
3180 1803 : psychParams = st->hTonalMDCTConc->psychParams;
3181 1803 : hFdCngCom = st->hFdCngDec->hFdCngCom;
3182 :
3183 1803 : set32_fx( whitenend_noise_shape, 0, L_FRAME16k );
3184 :
3185 1803 : IF( EQ_32( whitening_mode, ON_FIRST_LOST_FRAME ) )
3186 : {
3187 304 : IF( GT_16( st->core, TCX_20_CORE ) )
3188 : {
3189 6 : inc = 2;
3190 6 : move16();
3191 : }
3192 : ELSE
3193 : {
3194 298 : inc = 1;
3195 298 : move16();
3196 : }
3197 : }
3198 : ELSE
3199 : {
3200 1499 : IF( GT_16( st->last_core, TCX_20_CORE ) )
3201 : {
3202 21 : inc = 2;
3203 21 : move16();
3204 : }
3205 : ELSE
3206 : {
3207 1478 : inc = 1;
3208 1478 : move16();
3209 : }
3210 : }
3211 1803 : start_idx = shr( hFdCngCom->startBand, sub( inc, 1 ) );
3212 1803 : stop_idx = shr( L_frame, sub( inc, 1 ) );
3213 1803 : noiseLevelPtr = hFdCngCom->cngNoiseLevel;
3214 1803 : noiseLevelPtr_exp = hFdCngCom->cngNoiseLevelExp;
3215 1803 : move16();
3216 :
3217 570864 : FOR( Word16 j = start_idx; j < stop_idx; j++ )
3218 : {
3219 569061 : whitenend_noise_shape[j] = L_shr( *noiseLevelPtr, 3 );
3220 569061 : move32();
3221 569061 : noiseLevelPtr += inc;
3222 : }
3223 :
3224 1803 : IF( EQ_32( whitening_mode, ON_FIRST_LOST_FRAME ) )
3225 : {
3226 : Word32 scf[SNS_NPTS];
3227 :
3228 304 : sns_compute_scf_fx( whitenend_noise_shape, psychParams, L_frame, scf, sub( sub( 31, noiseLevelPtr_exp ), 3 ) );
3229 :
3230 304 : sns_interpolate_scalefactors_fx( scfs_int, scf, ENC );
3231 304 : sns_interpolate_scalefactors_fx( scfs_bg, scf, DEC );
3232 :
3233 304 : scfs_for_shaping = &scfs_int[0]; // Q16
3234 : }
3235 : ELSE /* whitening_mode == ON_FIRST_GOOD_FRAME */
3236 : {
3237 1499 : scfs_for_shaping = &scfs_bg[0]; // Q16
3238 : }
3239 :
3240 1803 : IF( sum32_sat( scfs_for_shaping, FDNS_NPTS ) > 0 )
3241 : {
3242 591 : q_wns = sub( sub( 31, noiseLevelPtr_exp ), 3 );
3243 591 : sns_shape_spectrum_fx( whitenend_noise_shape, &q_wns, psychParams, scfs_for_shaping, Q16, L_frame, NULL );
3244 :
3245 591 : IF( GT_16( add( q_wns, 1 ), sub( 31, hFdCngCom->cngNoiseLevelExp ) ) )
3246 : {
3247 152807 : FOR( i = 0; i < sub( stop_idx, start_idx ); i++ )
3248 : {
3249 152322 : hFdCngCom->cngNoiseLevel[i] = L_shr( whitenend_noise_shape[start_idx + i], sub( add( q_wns, hFdCngCom->cngNoiseLevelExp ), 30 ) ); //(q_wns + 1)
3250 152322 : move32();
3251 : }
3252 : }
3253 : ELSE
3254 : {
3255 106 : Copy32( whitenend_noise_shape + start_idx, hFdCngCom->cngNoiseLevel, sub( stop_idx, start_idx ) );
3256 :
3257 106 : scale_sig32( hFdCngCom->cngNoiseLevel + sub( stop_idx, start_idx ), sub( FFTCLDFBLEN, sub( stop_idx, start_idx ) ), sub( add( q_wns, hFdCngCom->cngNoiseLevelExp ), 30 ) );
3258 :
3259 106 : hFdCngCom->cngNoiseLevelExp = sub( Q30, q_wns ); // Exponent = 31 - (q_wns + 1)
3260 106 : move16();
3261 : }
3262 : }
3263 : ELSE
3264 : {
3265 1212 : set32_fx( hFdCngCom->cngNoiseLevel, 0, sub( stop_idx, start_idx ) );
3266 : }
3267 :
3268 1803 : pop_wmops();
3269 1803 : }
|