Line data Source code
1 : /******************************************************************************************************
2 :
3 : (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
4 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
5 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
6 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
7 : contributors to this repository. All Rights Reserved.
8 :
9 : This software is protected by copyright law and by international treaties.
10 : The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
11 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
12 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
13 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
14 : contributors to this repository retain full ownership rights in their respective contributions in
15 : the software. This notice grants no license of any kind, including but not limited to patent
16 : license, nor is any license granted by implication, estoppel or otherwise.
17 :
18 : Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
19 : contributions.
20 :
21 : This software is provided "AS IS", without any express or implied warranties. The software is in the
22 : development stage. It is intended exclusively for experts who have experience with such software and
23 : solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
24 : and fitness for a particular purpose are hereby disclaimed and excluded.
25 :
26 : Any dispute, controversy or claim arising under or in relation to providing this software shall be
27 : submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
28 : accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
29 : the United Nations Convention on Contracts on the International Sales of Goods.
30 :
31 : *******************************************************************************************************/
32 :
33 : /*====================================================================================
34 : EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
35 : ====================================================================================*/
36 :
37 : #define _USE_MATH_DEFINES
38 :
39 : #include <assert.h>
40 : #include <stdint.h>
41 : #include "options.h"
42 : #ifdef DEBUGGING
43 : #include "debug.h"
44 : #endif
45 : #include <math.h>
46 : #include "prot.h"
47 : #include "ivas_prot.h"
48 : #include "wmc_auto.h"
49 :
50 :
51 : /*******************************************************/
52 : /*-------------- public functions -------------------- */
53 : /*******************************************************/
54 :
55 47526 : ivas_error TonalMDCTConceal_Init(
56 : TonalMDCTConcealPtr hTonalMDCTConc,
57 : const uint16_t nSamples,
58 : const uint16_t nSamplesCore,
59 : const uint16_t nScaleFactors,
60 : TCX_CONFIG_HANDLE hTcxCfg )
61 : {
62 47526 : if ( nSamples > L_FRAME_MAX || nScaleFactors > FDNS_NPTS )
63 : {
64 0 : assert( nSamples <= L_FRAME_MAX );
65 0 : assert( nScaleFactors <= FDNS_NPTS );
66 0 : return ( IVAS_ERROR( IVAS_ERR_INTERNAL, "TonalMDCT FEC: Number of samples larger than max. block size\n" ) );
67 : }
68 47526 : assert( ( hTonalMDCTConc->nScaleFactors == nScaleFactors ) || ( hTonalMDCTConc->nSamples != nSamples ) ); /* If nSamples doesn't change then also nScaleFactors must stay the same */
69 :
70 47526 : hTonalMDCTConc->tcx_cfg = hTcxCfg;
71 47526 : hTonalMDCTConc->lastBlockData.spectralData = hTonalMDCTConc->spectralDataBuffers[0];
72 47526 : hTonalMDCTConc->secondLastBlockData.spectralData = hTonalMDCTConc->spectralDataBuffers[1];
73 47526 : hTonalMDCTConc->secondLastPowerSpectrum = hTonalMDCTConc->secondLastBlockData.spectralData;
74 47526 : hTonalMDCTConc->lastBlockData.scaleFactors = hTonalMDCTConc->scaleFactorsBuffers[0];
75 47526 : hTonalMDCTConc->secondLastBlockData.scaleFactors = hTonalMDCTConc->scaleFactorsBuffers[1];
76 47526 : hTonalMDCTConc->lastBlockData.blockIsValid = 0;
77 47526 : hTonalMDCTConc->secondLastBlockData.blockIsValid = 0;
78 47526 : hTonalMDCTConc->nSamples = 0;
79 47526 : hTonalMDCTConc->nScaleFactors = 0;
80 :
81 47526 : hTonalMDCTConc->lastBlockData.blockIsConcealed = 0;
82 47526 : hTonalMDCTConc->secondLastBlockData.blockIsConcealed = 0;
83 47526 : hTonalMDCTConc->pTCI = (TonalComponentsInfo *) hTonalMDCTConc->timeDataBuffer;
84 :
85 47526 : hTonalMDCTConc->lastPitchLag = 0;
86 :
87 47526 : if ( hTonalMDCTConc->nSamples != nSamples )
88 : {
89 47526 : hTonalMDCTConc->secondLastBlockData.blockIsValid = 0;
90 47526 : hTonalMDCTConc->lastBlockData.blockIsValid = 0;
91 : }
92 47526 : hTonalMDCTConc->nSamples = nSamples;
93 47526 : hTonalMDCTConc->nSamplesCore = nSamplesCore;
94 47526 : hTonalMDCTConc->nScaleFactors = nScaleFactors;
95 :
96 47526 : set_zero( hTonalMDCTConc->scaleFactorsBackground, FDNS_NPTS );
97 47526 : hTonalMDCTConc->scf_fadeout = 1.0f;
98 47526 : PsychoacousticParameters_Init( INT_FS_16k, L_FRAME16k, 64, 1, 1, &hTonalMDCTConc->psychParamsTCX20 );
99 47526 : PsychoacousticParameters_Init( INT_FS_16k, L_FRAME16k / 2, 64, 0, 1, &hTonalMDCTConc->psychParamsTCX10 );
100 47526 : hTonalMDCTConc->psychParams = NULL;
101 :
102 47526 : hTonalMDCTConc->last_block_nrg = 0.0f;
103 47526 : hTonalMDCTConc->curr_noise_nrg = 0.0f;
104 47526 : hTonalMDCTConc->faded_signal_nrg = 0.0f;
105 :
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 : /* just the second half of the second last pcm output is needed */
109 47526 : hTonalMDCTConc->secondLastPcmOut = &hTonalMDCTConc->timeDataBuffer[( 3 * L_FRAME_MAX ) / 2 - ( 3 * min( L_FRAME_MAX, nSamples ) ) / 2];
110 47526 : hTonalMDCTConc->lastPcmOut = &hTonalMDCTConc->timeDataBuffer[( 3 * L_FRAME_MAX ) / 2 - min( L_FRAME_MAX, nSamples )];
111 :
112 : /* If the second last frame was lost and concealed with tonal PLC, we
113 : reuse saved TonalComponentsInfo and don't update pcm buffers */
114 47526 : assert( sizeof( *hTonalMDCTConc->pTCI ) <= ( hTonalMDCTConc->lastPcmOut - hTonalMDCTConc->timeDataBuffer ) * sizeof( hTonalMDCTConc->timeDataBuffer[0] ) );
115 :
116 47526 : return IVAS_ERR_OK;
117 : }
118 :
119 :
120 2564757 : void TonalMDCTConceal_SaveFreqSignal(
121 : TonalMDCTConcealPtr hTonalMDCTConc,
122 : const float *mdctSpectrum,
123 : const uint16_t nNewSamples,
124 : const uint16_t nNewSamplesCore,
125 : const float *scaleFactors,
126 : const int16_t infoIGFStartLine )
127 : {
128 : float *temp;
129 : uint16_t nOldSamples;
130 :
131 2564757 : assert( nNewSamples > 0 && nNewSamples <= 2 * L_FRAME_MAX );
132 :
133 : /* Avoid overwriting hTonalMDCTConc->secondLastPowerSpectrum stored in spectralData,
134 : because it is needed if the second last and the current frame are lost
135 : and concealed using the Tonal MDCT PLC */
136 2564757 : if ( !hTonalMDCTConc->lastBlockData.tonalConcealmentActive || ( hTonalMDCTConc->lastBlockData.nSamples != nNewSamples ) )
137 : {
138 2563455 : if ( nNewSamples <= L_FRAME_MAX )
139 : {
140 : /* Shift the buffers */
141 2542968 : temp = hTonalMDCTConc->secondLastBlockData.spectralData; /* Save the pointer */
142 2542968 : hTonalMDCTConc->secondLastBlockData.spectralData = hTonalMDCTConc->lastBlockData.spectralData;
143 2542968 : hTonalMDCTConc->lastBlockData.spectralData = temp;
144 2542968 : temp = hTonalMDCTConc->secondLastBlockData.scaleFactors;
145 2542968 : hTonalMDCTConc->secondLastBlockData.scaleFactors = hTonalMDCTConc->lastBlockData.scaleFactors;
146 2542968 : hTonalMDCTConc->lastBlockData.scaleFactors = temp;
147 : }
148 : else
149 : {
150 : /* Order the buffers so that even transition frame can fit in if written into the first buffer */
151 20487 : hTonalMDCTConc->lastBlockData.spectralData = hTonalMDCTConc->spectralDataBuffers[0];
152 20487 : hTonalMDCTConc->secondLastBlockData.spectralData = hTonalMDCTConc->spectralDataBuffers[1];
153 20487 : hTonalMDCTConc->lastBlockData.scaleFactors = hTonalMDCTConc->scaleFactorsBuffers[0];
154 20487 : hTonalMDCTConc->secondLastBlockData.scaleFactors = hTonalMDCTConc->scaleFactorsBuffers[1];
155 : }
156 2563455 : nOldSamples = hTonalMDCTConc->lastBlockData.nSamples;
157 2563455 : hTonalMDCTConc->lastBlockData.nSamples = nNewSamples;
158 2563455 : hTonalMDCTConc->secondLastBlockData.nSamples = nOldSamples;
159 2563455 : nOldSamples = hTonalMDCTConc->lastBlockData.nSamplesCore;
160 2563455 : hTonalMDCTConc->lastBlockData.nSamplesCore = nNewSamplesCore;
161 2563455 : hTonalMDCTConc->secondLastBlockData.nSamplesCore = nOldSamples;
162 : }
163 :
164 2564757 : if ( ( nNewSamples > 0 ) && ( nNewSamples <= 2 * L_FRAME_MAX ) )
165 : {
166 : /* Store new data */
167 : int16_t i;
168 :
169 2564757 : hTonalMDCTConc->last_block_nrg = 0.0f;
170 1227338133 : for ( i = 0; i < infoIGFStartLine; i++ )
171 : {
172 1224773376 : hTonalMDCTConc->lastBlockData.spectralData[i] = mdctSpectrum[i];
173 1224773376 : hTonalMDCTConc->last_block_nrg += mdctSpectrum[i] * mdctSpectrum[i];
174 : }
175 923810901 : for ( ; i < nNewSamples; i++ )
176 : {
177 921246144 : hTonalMDCTConc->lastBlockData.spectralData[i] = mdctSpectrum[i];
178 : }
179 :
180 2564757 : mvr2r( scaleFactors, hTonalMDCTConc->lastBlockData.scaleFactors, hTonalMDCTConc->nScaleFactors );
181 : }
182 :
183 2564757 : return;
184 : }
185 :
186 :
187 2842746 : void TonalMDCTConceal_UpdateState(
188 : TonalMDCTConcealPtr hTonalMDCTConc,
189 : const int16_t nNewSamples,
190 : const float pitchLag,
191 : const int16_t badBlock,
192 : const int16_t tonalConcealmentActive )
193 : {
194 : int16_t newBlockIsValid;
195 :
196 2842746 : assert( !( !badBlock && tonalConcealmentActive ) );
197 :
198 2842746 : if ( badBlock )
199 : {
200 49758 : newBlockIsValid = hTonalMDCTConc->lastBlockData.blockIsValid;
201 : }
202 : else
203 : {
204 2792988 : newBlockIsValid = ( nNewSamples <= 2 * L_FRAME_MAX ) && ( nNewSamples > 0 );
205 : }
206 :
207 : /* Shift old state */
208 2842746 : hTonalMDCTConc->secondLastBlockData.blockIsConcealed = hTonalMDCTConc->lastBlockData.blockIsConcealed;
209 2842746 : hTonalMDCTConc->secondLastBlockData.blockIsValid = hTonalMDCTConc->lastBlockData.blockIsValid;
210 2842746 : hTonalMDCTConc->secondLastBlockData.tonalConcealmentActive = hTonalMDCTConc->lastBlockData.tonalConcealmentActive;
211 :
212 : /* Store new state */
213 2842746 : hTonalMDCTConc->lastBlockData.blockIsConcealed = badBlock;
214 2842746 : hTonalMDCTConc->lastBlockData.blockIsValid = newBlockIsValid;
215 2842746 : hTonalMDCTConc->lastBlockData.tonalConcealmentActive = tonalConcealmentActive;
216 2842746 : hTonalMDCTConc->lastPitchLag = pitchLag;
217 :
218 2842746 : return;
219 : }
220 :
221 :
222 5931 : static void FindPhases(
223 : const TonalMDCTConcealPtr hTonalMDCTConc,
224 : const float secondLastMDCT[],
225 : const float secondLastMDST[] )
226 : {
227 : int16_t i;
228 : int16_t l;
229 : float *pCurrentPhase;
230 :
231 5931 : pCurrentPhase = hTonalMDCTConc->pTCI->phase_currentFramePredicted;
232 : /* for each index/index group */
233 17874 : for ( i = 0; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
234 : {
235 95430 : for ( l = hTonalMDCTConc->pTCI->lowerIndex[i]; l <= hTonalMDCTConc->pTCI->upperIndex[i]; l++ )
236 : {
237 83487 : *pCurrentPhase++ = (float) atan2( secondLastMDST[l], secondLastMDCT[l] );
238 : }
239 : }
240 :
241 5931 : return;
242 : }
243 :
244 : #define CNST_bandwidth 7.0f
245 : #define CNST_m (float) cos( EVS_PI / CNST_bandwidth )
246 : #define CNST_s (float) cos( ( 3 * EVS_PI ) / CNST_bandwidth )
247 : #define CNST_n (float) sin( EVS_PI / CNST_bandwidth )
248 : #define CNST_j (float) sin( ( 3 * EVS_PI ) / CNST_bandwidth )
249 : #define CNST_G (float) ( 1.0 / ( 2 * 1.36 ) )
250 : #define CNST_maxRatio 44.8f /* Maximum ratio |ODFT[k-1]|/|ODFT[k+1]| is 16.5 dB, that is maximum ratio (for fractional = 0) is (cos(EVS_PI/bandwidth)/cos(3PI/bandwidth))^1.36 */
251 :
252 :
253 5931 : static void FindPhaseDifferences(
254 : TonalMDCTConcealPtr const hTonalMDCTConc,
255 : float powerSpectrum[] )
256 : {
257 : int16_t i, k;
258 : float odft_left, odft_right;
259 : float *phaseDiff;
260 : float fractional;
261 : float Q, a;
262 :
263 5931 : phaseDiff = hTonalMDCTConc->pTCI->phaseDiff;
264 17874 : for ( i = 0; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
265 : {
266 11943 : k = hTonalMDCTConc->pTCI->indexOfTonalPeak[i];
267 11943 : odft_left = powerSpectrum[k - 1];
268 11943 : odft_right = powerSpectrum[k + 1];
269 11943 : if ( odft_left >= CNST_maxRatio * odft_right )
270 : {
271 72 : a = (float) tan( 0.0f * EVS_PI / CNST_bandwidth );
272 : }
273 : else
274 : {
275 11871 : if ( odft_right >= CNST_maxRatio * odft_left )
276 : {
277 123 : a = (float) tan( 2.0f * EVS_PI / CNST_bandwidth );
278 : }
279 : else
280 : {
281 11748 : Q = (float) pow( odft_left / odft_right, CNST_G );
282 11748 : a = ( CNST_m - Q * CNST_s ) / ( CNST_n + Q * CNST_j );
283 : }
284 : }
285 11943 : fractional = (float) atan( a ) * ( CNST_bandwidth / 2.0f );
286 11943 : assert( ( fractional >= 0 ) && ( fractional <= EVS_PI + 1.192092896e-07F ) );
287 11943 : phaseDiff[i] = fractional + EVS_PI * ( k % 4 );
288 : }
289 :
290 5931 : return;
291 : }
292 :
293 5931 : static void CalcPowerSpec(
294 : const float *mdctSpec,
295 : const float *mdstSpec,
296 : const int16_t nSamples,
297 : float floorPowerSpectrum,
298 : float *powerSpec )
299 : {
300 : int16_t k;
301 : float x;
302 :
303 2944770 : for ( k = 1; k <= nSamples - 2; k++ )
304 : {
305 2938839 : x = mdctSpec[k] * mdctSpec[k] + mdstSpec[k] * mdstSpec[k];
306 2938839 : powerSpec[k] = max( floorPowerSpectrum, x );
307 : }
308 5931 : powerSpec[0] = 0.5f * powerSpec[1];
309 5931 : powerSpec[nSamples - 1] = 0.5f * powerSpec[nSamples - 2];
310 :
311 5931 : return;
312 : }
313 :
314 5931 : static void CalcPowerSpecAndDetectTonalComponents(
315 : const TonalMDCTConcealPtr hTonalMDCTConc,
316 : float secondLastMDST[],
317 : float secondLastMDCT[],
318 : const float pitchLag,
319 : const PsychoacousticParameters *psychParamsCurrent )
320 : {
321 : int16_t i, nSamples;
322 : float floorPowerSpectrum; /* Minimum significant value of a spectral line in the power spectrum */
323 : float powerSpectrum[L_FRAME_MAX]; /* 32 bits are required */
324 : float invScaleFactors[FDNS_NPTS];
325 : int16_t nBands;
326 :
327 5931 : nSamples = hTonalMDCTConc->nNonZeroSamples;
328 :
329 : /* It is taken into account that the MDCT is not normalized. */
330 5931 : floorPowerSpectrum = hTonalMDCTConc->nSamples * hTonalMDCTConc->nSamples / 400.0f;
331 5931 : CalcPowerSpec( secondLastMDCT, secondLastMDST, nSamples, floorPowerSpectrum, powerSpectrum );
332 :
333 : /* This setting to minimal level is required because the power spectrum is used in the threshold adaptation using the pitch up to hTonalMDCTConc->nSamples. */
334 5931 : set_f( powerSpectrum + nSamples, floorPowerSpectrum, hTonalMDCTConc->nSamples - nSamples );
335 : /* this setting to zero is needed since the FDNS needs to be called
336 : with hTonalMDCTConc->nSamplesCore; it relevant only for nb; it has no effect
337 : to the output, but memory checker may complain otherwise due to the
338 : usage of uninitialized values */
339 :
340 5931 : if ( hTonalMDCTConc->nSamplesCore > hTonalMDCTConc->nSamples )
341 : {
342 174 : set_zero( powerSpectrum + hTonalMDCTConc->nSamples, hTonalMDCTConc->nSamplesCore - hTonalMDCTConc->nSamples );
343 : }
344 :
345 5931 : DetectTonalComponents( hTonalMDCTConc->pTCI->indexOfTonalPeak, hTonalMDCTConc->pTCI->lowerIndex, hTonalMDCTConc->pTCI->upperIndex, &hTonalMDCTConc->pTCI->numIndexes, hTonalMDCTConc->lastPitchLag, pitchLag,
346 5931 : hTonalMDCTConc->lastBlockData.spectralData, hTonalMDCTConc->lastBlockData.scaleFactors, powerSpectrum, nSamples, hTonalMDCTConc->nSamplesCore, floorPowerSpectrum, psychParamsCurrent );
347 :
348 5931 : FindPhases( hTonalMDCTConc, secondLastMDCT, secondLastMDST );
349 :
350 5931 : FindPhaseDifferences( hTonalMDCTConc, powerSpectrum );
351 :
352 5931 : if ( hTonalMDCTConc->pTCI->numIndexes > 0 )
353 : {
354 2166 : hTonalMDCTConc->secondLastPowerSpectrum = hTonalMDCTConc->secondLastBlockData.spectralData;
355 :
356 1143459 : for ( i = 0; i < nSamples; i++ )
357 : {
358 1141293 : powerSpectrum[i] = (float) sqrt( powerSpectrum[i] );
359 : }
360 :
361 140790 : for ( i = 0; i < hTonalMDCTConc->nScaleFactors; i++ )
362 : {
363 138624 : invScaleFactors[i] = 1.0f / hTonalMDCTConc->secondLastBlockData.scaleFactors[i];
364 : }
365 :
366 2166 : if ( psychParamsCurrent == NULL )
367 : {
368 906 : nBands = FDNS_NPTS;
369 906 : mdct_noiseShaping( powerSpectrum, hTonalMDCTConc->nSamplesCore, invScaleFactors, nBands );
370 : }
371 : else
372 : {
373 1260 : sns_shape_spectrum( powerSpectrum, psychParamsCurrent, invScaleFactors, hTonalMDCTConc->nSamplesCore );
374 1260 : nBands = psychParamsCurrent->nBands;
375 : }
376 :
377 2166 : v_multc( powerSpectrum + hTonalMDCTConc->nSamplesCore, invScaleFactors[nBands - 1], powerSpectrum + hTonalMDCTConc->nSamplesCore, hTonalMDCTConc->nSamples - hTonalMDCTConc->nSamplesCore );
378 2166 : mvr2r( powerSpectrum, hTonalMDCTConc->secondLastPowerSpectrum, hTonalMDCTConc->nSamples ); /* 16 bits are now enough for storing the power spectrum */
379 : }
380 :
381 5931 : return;
382 : }
383 :
384 :
385 11862 : static void CalcMDXT(
386 : const TonalMDCTConcealPtr hTonalMDCTConc,
387 : const char type,
388 : const float *timeSignal,
389 : float *mdxtOutput )
390 : {
391 : float windowedTimeSignal[L_FRAME_PLUS + 2 * L_MDCT_OVLP_MAX];
392 : int16_t left_overlap, right_overlap;
393 : int16_t L_frame;
394 :
395 11862 : L_frame = hTonalMDCTConc->nSamples;
396 11862 : WindowSignal( hTonalMDCTConc->tcx_cfg, hTonalMDCTConc->tcx_cfg->tcx_offsetFB, FULL_OVERLAP, FULL_OVERLAP, &left_overlap, &right_overlap, timeSignal, &L_frame, windowedTimeSignal, 1, 1 );
397 :
398 11862 : if ( type == 'S' )
399 : {
400 5931 : TCX_MDST( windowedTimeSignal, mdxtOutput, left_overlap, L_frame - ( left_overlap + right_overlap ) / 2, right_overlap, EVS_MONO );
401 : }
402 : else
403 : {
404 5931 : TCX_MDCT( windowedTimeSignal, mdxtOutput, left_overlap, L_frame - ( left_overlap + right_overlap ) / 2, right_overlap, EVS_MONO );
405 : }
406 :
407 11862 : return;
408 : }
409 :
410 :
411 7215 : void TonalMDCTConceal_Detect(
412 : const TonalMDCTConcealPtr hTonalMDCTConc,
413 : const float pitchLag,
414 : int16_t *numIndices,
415 : const PsychoacousticParameters *psychParamsCurrent )
416 : {
417 : float secondLastMDST[L_FRAME_MAX]; /* 32 bits are required */
418 : float secondLastMDCT[L_FRAME_MAX]; /* 32 bits are required */
419 7215 : float *powerSpectrum = secondLastMDST;
420 : int16_t i, nSamples;
421 : int16_t nBands;
422 :
423 7215 : nSamples = hTonalMDCTConc->nSamples;
424 7215 : if ( hTonalMDCTConc->lastBlockData.blockIsValid && hTonalMDCTConc->secondLastBlockData.blockIsValid && ( hTonalMDCTConc->lastBlockData.nSamples == nSamples ) && ( hTonalMDCTConc->secondLastBlockData.nSamples == nSamples ) && ( !hTonalMDCTConc->secondLastBlockData.blockIsConcealed || hTonalMDCTConc->secondLastBlockData.tonalConcealmentActive || ( pitchLag != 0 ) ) )
425 : {
426 : /* Safety if the second last frame was concealed and tonal concealment was inactive */
427 :
428 6066 : if ( !hTonalMDCTConc->lastBlockData.blockIsConcealed )
429 : {
430 6066 : if ( !hTonalMDCTConc->secondLastBlockData.tonalConcealmentActive )
431 : {
432 5931 : CalcMDXT( hTonalMDCTConc, 'S', hTonalMDCTConc->secondLastPcmOut, secondLastMDST );
433 5931 : CalcMDXT( hTonalMDCTConc, 'C', hTonalMDCTConc->secondLastPcmOut, secondLastMDCT );
434 5931 : hTonalMDCTConc->nNonZeroSamples = 0;
435 4600491 : for ( i = 0; i < hTonalMDCTConc->nSamples; i++ )
436 : {
437 4594560 : if ( hTonalMDCTConc->secondLastBlockData.spectralData[i] != 0 )
438 : {
439 2656377 : hTonalMDCTConc->nNonZeroSamples = i;
440 : }
441 : }
442 : /* 23 is the maximum length of the MA filter in getEnvelope */
443 5931 : hTonalMDCTConc->nNonZeroSamples = min( hTonalMDCTConc->nSamples, hTonalMDCTConc->nNonZeroSamples + 23 );
444 5931 : CalcPowerSpecAndDetectTonalComponents( hTonalMDCTConc, secondLastMDST, secondLastMDCT, pitchLag, psychParamsCurrent );
445 : }
446 : else
447 : {
448 : /* 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. */
449 : /* That is why we reuse the already stored information about the concealed spectrum in the second last frame */
450 135 : nSamples = hTonalMDCTConc->nNonZeroSamples;
451 135 : mvr2r( hTonalMDCTConc->secondLastPowerSpectrum, powerSpectrum, nSamples ); /* Convert from 16 bits to 32 bits */
452 135 : if ( psychParamsCurrent == NULL )
453 : {
454 48 : nBands = FDNS_NPTS;
455 48 : mdct_noiseShaping( powerSpectrum, hTonalMDCTConc->nSamplesCore, hTonalMDCTConc->secondLastBlockData.scaleFactors, nBands );
456 : }
457 : else
458 : {
459 87 : sns_shape_spectrum( powerSpectrum, psychParamsCurrent, hTonalMDCTConc->secondLastBlockData.scaleFactors, hTonalMDCTConc->nSamplesCore );
460 87 : nBands = psychParamsCurrent->nBands;
461 : }
462 :
463 135 : v_multc( powerSpectrum + hTonalMDCTConc->nSamplesCore, hTonalMDCTConc->secondLastBlockData.scaleFactors[nBands - 1], powerSpectrum + hTonalMDCTConc->nSamplesCore, nSamples - hTonalMDCTConc->nSamplesCore );
464 135 : v_mult( powerSpectrum, powerSpectrum, powerSpectrum, nSamples );
465 :
466 135 : RefineTonalComponents( hTonalMDCTConc->pTCI->indexOfTonalPeak, hTonalMDCTConc->pTCI->lowerIndex, hTonalMDCTConc->pTCI->upperIndex, hTonalMDCTConc->pTCI->phaseDiff,
467 135 : hTonalMDCTConc->pTCI->phase_currentFramePredicted, &hTonalMDCTConc->pTCI->numIndexes, hTonalMDCTConc->lastPitchLag, pitchLag,
468 135 : hTonalMDCTConc->lastBlockData.spectralData, hTonalMDCTConc->lastBlockData.scaleFactors, powerSpectrum,
469 135 : nSamples, hTonalMDCTConc->nSamplesCore, hTonalMDCTConc->nSamples * hTonalMDCTConc->nSamples / 400.0f /* floorPowerSpectrum */, psychParamsCurrent );
470 : }
471 : }
472 : }
473 : else
474 : {
475 1149 : hTonalMDCTConc->pTCI->numIndexes = 0;
476 : }
477 :
478 7215 : *numIndices = hTonalMDCTConc->pTCI->numIndexes;
479 :
480 7215 : return;
481 : }
482 :
483 :
484 34524 : void TonalMDCTConceal_InsertNoise(
485 : const TonalMDCTConcealPtr hTonalMDCTConc, /*IN */
486 : float *mdctSpectrum, /*OUT*/
487 : const int16_t tonalConcealmentActive,
488 : int16_t *pSeed,
489 : const float tiltCompFactor,
490 : const float crossfadeGain,
491 : const float concealment_noise[L_FRAME48k],
492 : const float cngLevelBackgroundTrace_bfi,
493 : const int16_t crossOverFreq )
494 : {
495 : int16_t i, l;
496 : float x, y;
497 : Word16 rnd;
498 : float g, nrgNoiseInLastFrame, nrgWhiteNoise, tiltFactor, tilt;
499 : float last_block_nrg_correct;
500 :
501 34524 : push_wmops( "InsertNoise" );
502 :
503 34524 : g = 1.0f - crossfadeGain;
504 34524 : if ( !hTonalMDCTConc->lastBlockData.blockIsConcealed )
505 : {
506 20784 : rnd = 1977;
507 : }
508 : else
509 : {
510 13740 : rnd = *pSeed;
511 : }
512 :
513 : /* based on what is done in tcx_noise_filling() */
514 : /* always initialize these to avoid compiler warnings */
515 34524 : tiltFactor = (float) pow( max( 0.375f, tiltCompFactor ), 1.0f / hTonalMDCTConc->lastBlockData.nSamples );
516 34524 : tilt = 1.0f;
517 34524 : nrgNoiseInLastFrame = 0.0f;
518 34524 : nrgWhiteNoise = 0.0f;
519 34524 : hTonalMDCTConc->faded_signal_nrg = 0.0f;
520 34524 : last_block_nrg_correct = 0.0f;
521 :
522 34524 : if ( !hTonalMDCTConc->lastBlockData.blockIsValid )
523 : {
524 : /* may just become active if the very first frame is lost */
525 0 : set_f( mdctSpectrum, 0.0f, hTonalMDCTConc->nSamples );
526 : }
527 34524 : else if ( concealment_noise != NULL )
528 : {
529 11073 : if ( !tonalConcealmentActive )
530 : {
531 : /* if fadeout has not started yet, only apply sign scrambling */
532 10662 : if ( crossfadeGain == 1.0f )
533 : {
534 2224293 : for ( i = 0; i < crossOverFreq; i++ )
535 : {
536 2218464 : if ( concealment_noise[i] > 0 )
537 : {
538 1154832 : mdctSpectrum[i] = hTonalMDCTConc->lastBlockData.spectralData[i];
539 : }
540 : else
541 : {
542 1063632 : mdctSpectrum[i] = -hTonalMDCTConc->lastBlockData.spectralData[i];
543 : }
544 : }
545 :
546 1399845 : for ( l = crossOverFreq; l < hTonalMDCTConc->lastBlockData.nSamples; l++ )
547 : {
548 1394016 : mdctSpectrum[l] = 0.0f;
549 : }
550 : }
551 : /* actual fadeout is done in this case */
552 : else
553 : {
554 4833 : g *= (float) sqrt( cngLevelBackgroundTrace_bfi / hTonalMDCTConc->curr_noise_nrg );
555 :
556 1843809 : for ( i = 0; i < crossOverFreq; i++ )
557 : {
558 1838976 : x = hTonalMDCTConc->lastBlockData.spectralData[i];
559 1838976 : y = concealment_noise[i];
560 :
561 1838976 : if ( y > 0 )
562 : {
563 96642 : mdctSpectrum[i] = g * y + crossfadeGain * x;
564 : }
565 : else
566 : {
567 1742334 : mdctSpectrum[i] = g * y - crossfadeGain * x;
568 : }
569 :
570 1838976 : hTonalMDCTConc->faded_signal_nrg += mdctSpectrum[i] * mdctSpectrum[i];
571 : }
572 1279137 : for ( l = crossOverFreq; l < hTonalMDCTConc->lastBlockData.nSamples; l++ )
573 : {
574 1274304 : mdctSpectrum[l] = 0.0f;
575 : }
576 : }
577 : }
578 : else
579 : {
580 411 : assert( hTonalMDCTConc->pTCI->numIndexes > 0 );
581 :
582 : /* initialize bins of tonal components with zero: basically not
583 : necessary, but currently the whole spectrum is rescaled in
584 : mdct_noiseShaping() and then there would be a processing of
585 : uninitialized values */
586 3396 : for ( i = 0; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
587 : {
588 23874 : for ( l = hTonalMDCTConc->pTCI->lowerIndex[i]; l <= hTonalMDCTConc->pTCI->upperIndex[i]; l++ )
589 : {
590 20889 : mdctSpectrum[l] = 0;
591 20889 : if ( l < crossOverFreq )
592 : {
593 20658 : last_block_nrg_correct += hTonalMDCTConc->lastBlockData.spectralData[l] * hTonalMDCTConc->lastBlockData.spectralData[l];
594 20658 : hTonalMDCTConc->curr_noise_nrg -= concealment_noise[l] * concealment_noise[l];
595 : }
596 : }
597 : }
598 :
599 : /* if fadeout has not started yet, only apply sign scrambling */
600 411 : if ( crossfadeGain == 1.0f )
601 : {
602 16530 : for ( l = 0; l < hTonalMDCTConc->pTCI->lowerIndex[0]; l++ )
603 : {
604 16185 : if ( concealment_noise[l] > 0 )
605 : {
606 7806 : mdctSpectrum[l] = hTonalMDCTConc->lastBlockData.spectralData[l];
607 : }
608 : else
609 : {
610 8379 : mdctSpectrum[l] = -hTonalMDCTConc->lastBlockData.spectralData[l];
611 : }
612 : }
613 2604 : for ( i = 1; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
614 : {
615 30717 : for ( l = hTonalMDCTConc->pTCI->upperIndex[i - 1] + 1; l < hTonalMDCTConc->pTCI->lowerIndex[i]; l++ )
616 : {
617 28458 : if ( concealment_noise[l] > 0 )
618 : {
619 14901 : mdctSpectrum[l] = hTonalMDCTConc->lastBlockData.spectralData[l];
620 : }
621 : else
622 : {
623 13557 : mdctSpectrum[l] = -hTonalMDCTConc->lastBlockData.spectralData[l];
624 : }
625 : }
626 : }
627 :
628 68226 : for ( l = hTonalMDCTConc->pTCI->upperIndex[hTonalMDCTConc->pTCI->numIndexes - 1] + 1; l < crossOverFreq; l++ )
629 : {
630 67881 : if ( concealment_noise[l] > 0 )
631 : {
632 35424 : mdctSpectrum[l] = hTonalMDCTConc->lastBlockData.spectralData[l];
633 : }
634 : else
635 : {
636 32457 : mdctSpectrum[l] = -hTonalMDCTConc->lastBlockData.spectralData[l];
637 : }
638 : }
639 :
640 60705 : for ( l = crossOverFreq; l < hTonalMDCTConc->lastBlockData.nSamples; l++ )
641 : {
642 60360 : mdctSpectrum[l] = hTonalMDCTConc->lastBlockData.spectralData[l];
643 : }
644 : }
645 : /* actual fadeout is done in this case */
646 : else
647 : {
648 66 : g *= (float) sqrt( cngLevelBackgroundTrace_bfi / hTonalMDCTConc->curr_noise_nrg );
649 :
650 4233 : for ( l = 0; l < hTonalMDCTConc->pTCI->lowerIndex[0]; l++ )
651 : {
652 4167 : x = hTonalMDCTConc->lastBlockData.spectralData[l];
653 4167 : y = concealment_noise[l];
654 :
655 4167 : if ( y > 0 )
656 : {
657 339 : mdctSpectrum[l] = g * y + crossfadeGain * x;
658 : }
659 : else
660 : {
661 3828 : mdctSpectrum[l] = g * y - crossfadeGain * x;
662 : }
663 4167 : hTonalMDCTConc->faded_signal_nrg += mdctSpectrum[l] * mdctSpectrum[l];
664 : }
665 381 : for ( i = 1; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
666 : {
667 6222 : for ( l = hTonalMDCTConc->pTCI->upperIndex[i - 1] + 1; l < hTonalMDCTConc->pTCI->lowerIndex[i]; l++ )
668 : {
669 5907 : x = hTonalMDCTConc->lastBlockData.spectralData[l];
670 5907 : y = concealment_noise[l];
671 :
672 5907 : if ( y > 0 )
673 : {
674 384 : mdctSpectrum[l] = g * y + crossfadeGain * x;
675 : }
676 : else
677 : {
678 5523 : mdctSpectrum[l] = g * y - crossfadeGain * x;
679 : }
680 5907 : hTonalMDCTConc->faded_signal_nrg += mdctSpectrum[l] * mdctSpectrum[l];
681 : }
682 : }
683 :
684 14049 : for ( l = hTonalMDCTConc->pTCI->upperIndex[hTonalMDCTConc->pTCI->numIndexes - 1] + 1; l < crossOverFreq; l++ )
685 : {
686 13983 : x = hTonalMDCTConc->lastBlockData.spectralData[l];
687 13983 : y = concealment_noise[l];
688 :
689 13983 : if ( y > 0 )
690 : {
691 186 : mdctSpectrum[l] = g * y + crossfadeGain * x;
692 : }
693 : else
694 : {
695 13797 : mdctSpectrum[l] = g * y - crossfadeGain * x;
696 : }
697 13983 : hTonalMDCTConc->faded_signal_nrg += mdctSpectrum[l] * mdctSpectrum[l];
698 : }
699 :
700 13914 : for ( l = crossOverFreq; l < hTonalMDCTConc->lastBlockData.nSamples; l++ )
701 : {
702 13848 : mdctSpectrum[l] = 0.0f;
703 : }
704 : }
705 : }
706 :
707 11073 : if ( hTonalMDCTConc->faded_signal_nrg > 0.0f && hTonalMDCTConc->curr_noise_nrg > MDCT_ST_PLC_FADEOUT_MIN_NOISE_NRG )
708 : {
709 : float nrg_corr_factor;
710 :
711 498 : nrg_corr_factor = sqrtf( ( hTonalMDCTConc->last_block_nrg - last_block_nrg_correct ) / hTonalMDCTConc->faded_signal_nrg );
712 498 : v_multc( mdctSpectrum, nrg_corr_factor, mdctSpectrum, crossOverFreq );
713 : }
714 : }
715 : else
716 : {
717 23451 : if ( !tonalConcealmentActive )
718 : {
719 10039419 : for ( i = 0; i < crossOverFreq; i++ )
720 : {
721 10017426 : x = hTonalMDCTConc->lastBlockData.spectralData[i];
722 10017426 : nrgNoiseInLastFrame += x * x;
723 10017426 : rnd = own_random( &rnd );
724 10017426 : mdctSpectrum[i] = tilt * rnd;
725 10017426 : tilt *= tiltFactor;
726 10017426 : nrgWhiteNoise += mdctSpectrum[i] * mdctSpectrum[i];
727 : }
728 21993 : if ( nrgWhiteNoise > 0 )
729 : {
730 21993 : g *= (float) sqrt( nrgNoiseInLastFrame / nrgWhiteNoise );
731 : }
732 10039419 : for ( i = 0; i < crossOverFreq; i++ )
733 : {
734 10017426 : x = hTonalMDCTConc->lastBlockData.spectralData[i];
735 10017426 : y = mdctSpectrum[i];
736 :
737 10017426 : if ( y > 0 )
738 : {
739 5030757 : mdctSpectrum[i] = g * y + crossfadeGain * x;
740 : }
741 : else
742 : {
743 4986669 : mdctSpectrum[i] = g * y - crossfadeGain * x;
744 : }
745 : }
746 :
747 6494487 : for ( l = crossOverFreq; l < hTonalMDCTConc->lastBlockData.nSamples; l++ )
748 : {
749 6472494 : mdctSpectrum[l] = hTonalMDCTConc->lastBlockData.spectralData[l];
750 : }
751 : }
752 : else
753 : {
754 1458 : assert( hTonalMDCTConc->pTCI->numIndexes > 0 );
755 103911 : for ( l = 0; l < hTonalMDCTConc->pTCI->lowerIndex[0]; l++ )
756 : {
757 102453 : x = hTonalMDCTConc->lastBlockData.spectralData[l];
758 102453 : rnd = own_random( &rnd );
759 102453 : mdctSpectrum[l] = tilt * rnd;
760 102453 : tilt *= tiltFactor;
761 102453 : nrgNoiseInLastFrame += x * x;
762 102453 : nrgWhiteNoise += mdctSpectrum[l] * mdctSpectrum[l];
763 : }
764 :
765 7443 : for ( i = 1; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
766 : {
767 5985 : tilt *= (float) pow( tiltFactor, hTonalMDCTConc->pTCI->upperIndex[i - 1] - hTonalMDCTConc->pTCI->lowerIndex[i - 1] + 1 );
768 107142 : for ( l = hTonalMDCTConc->pTCI->upperIndex[i - 1] + 1; l < hTonalMDCTConc->pTCI->lowerIndex[i]; l++ )
769 : {
770 101157 : x = hTonalMDCTConc->lastBlockData.spectralData[l];
771 101157 : rnd = own_random( &rnd );
772 101157 : mdctSpectrum[l] = tilt * rnd;
773 101157 : tilt *= tiltFactor;
774 101157 : nrgNoiseInLastFrame += x * x;
775 101157 : nrgWhiteNoise += mdctSpectrum[l] * mdctSpectrum[l];
776 : }
777 : }
778 1458 : tilt *= (float) pow( tiltFactor, hTonalMDCTConc->pTCI->upperIndex[hTonalMDCTConc->pTCI->numIndexes - 1] - hTonalMDCTConc->pTCI->lowerIndex[hTonalMDCTConc->pTCI->numIndexes - 1] + 1 );
779 :
780 364794 : for ( l = hTonalMDCTConc->pTCI->upperIndex[hTonalMDCTConc->pTCI->numIndexes - 1] + 1; l < crossOverFreq; l++ )
781 : {
782 363336 : x = hTonalMDCTConc->lastBlockData.spectralData[l];
783 363336 : rnd = own_random( &rnd );
784 363336 : mdctSpectrum[l] = tilt * rnd;
785 363336 : tilt *= tiltFactor;
786 363336 : nrgNoiseInLastFrame += x * x;
787 363336 : nrgWhiteNoise += mdctSpectrum[l] * mdctSpectrum[l];
788 : }
789 1458 : if ( nrgWhiteNoise > 0 )
790 : {
791 1458 : g *= (float) sqrt( nrgNoiseInLastFrame / nrgWhiteNoise );
792 : }
793 103911 : for ( l = 0; l < hTonalMDCTConc->pTCI->lowerIndex[0]; l++ )
794 : {
795 102453 : x = hTonalMDCTConc->lastBlockData.spectralData[l];
796 102453 : y = mdctSpectrum[l];
797 :
798 102453 : if ( y > 0 )
799 : {
800 52725 : mdctSpectrum[l] = g * y + crossfadeGain * x;
801 : }
802 : else
803 : {
804 49728 : mdctSpectrum[l] = g * y - crossfadeGain * x;
805 : }
806 : }
807 7443 : for ( i = 1; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
808 : {
809 107142 : for ( l = hTonalMDCTConc->pTCI->upperIndex[i - 1] + 1; l < hTonalMDCTConc->pTCI->lowerIndex[i]; l++ )
810 : {
811 101157 : x = hTonalMDCTConc->lastBlockData.spectralData[l];
812 101157 : y = mdctSpectrum[l];
813 :
814 101157 : if ( y > 0 )
815 : {
816 54105 : mdctSpectrum[l] = g * y + crossfadeGain * x;
817 : }
818 : else
819 : {
820 47052 : mdctSpectrum[l] = g * y - crossfadeGain * x;
821 : }
822 : }
823 : }
824 : /* initialize bins of tonal components with zero: basically not
825 : necessary, but currently the whole spectrum is rescaled in
826 : mdct_noiseShaping() and then there would be a processing of
827 : uninitialized values */
828 8901 : for ( i = 0; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
829 : {
830 59517 : for ( l = hTonalMDCTConc->pTCI->lowerIndex[i]; l <= hTonalMDCTConc->pTCI->upperIndex[i]; l++ )
831 : {
832 52074 : mdctSpectrum[l] = 0;
833 : }
834 : }
835 364794 : for ( l = hTonalMDCTConc->pTCI->upperIndex[hTonalMDCTConc->pTCI->numIndexes - 1] + 1; l < crossOverFreq; l++ )
836 : {
837 363336 : x = hTonalMDCTConc->lastBlockData.spectralData[l];
838 363336 : y = mdctSpectrum[l];
839 :
840 363336 : if ( y > 0 )
841 : {
842 179244 : mdctSpectrum[l] = g * y + crossfadeGain * x;
843 : }
844 : else
845 : {
846 184092 : mdctSpectrum[l] = g * y - crossfadeGain * x;
847 : }
848 : }
849 :
850 666558 : for ( l = crossOverFreq; l < hTonalMDCTConc->lastBlockData.nSamples; l++ )
851 : {
852 665100 : mdctSpectrum[l] = hTonalMDCTConc->lastBlockData.spectralData[l];
853 : }
854 : }
855 : }
856 :
857 34524 : *pSeed = rnd;
858 :
859 34524 : pop_wmops();
860 :
861 34524 : return;
862 : }
863 :
864 :
865 1869 : void TonalMDCTConceal_Apply(
866 : TonalMDCTConcealPtr hTonalMDCTConc, /*IN */
867 : float *mdctSpectrum, /*OUT */
868 : const PsychoacousticParameters *psychParamsCurrent )
869 : {
870 : int16_t i, l;
871 : float *phaseDiff, *pCurrentPhase;
872 : float phaseToAdd;
873 : float powerSpectrum[L_FRAME_MAX];
874 : int16_t nSamples;
875 : int16_t nBands;
876 :
877 1869 : if ( hTonalMDCTConc->lastBlockData.blockIsValid & hTonalMDCTConc->secondLastBlockData.blockIsValid )
878 : {
879 1869 : assert( hTonalMDCTConc->pTCI->numIndexes > 0 );
880 :
881 1869 : nSamples = hTonalMDCTConc->nNonZeroSamples;
882 1869 : assert( hTonalMDCTConc->pTCI->upperIndex[hTonalMDCTConc->pTCI->numIndexes - 1] < nSamples );
883 1869 : mvr2r( hTonalMDCTConc->secondLastPowerSpectrum, powerSpectrum, nSamples ); /* Convert from 16 bits to 32 bits */
884 1869 : if ( psychParamsCurrent == NULL )
885 : {
886 834 : nBands = FDNS_NPTS;
887 834 : mdct_noiseShaping( powerSpectrum, hTonalMDCTConc->nSamplesCore, hTonalMDCTConc->secondLastBlockData.scaleFactors, nBands );
888 : }
889 : else
890 : {
891 1035 : sns_shape_spectrum( powerSpectrum, psychParamsCurrent, hTonalMDCTConc->secondLastBlockData.scaleFactors, hTonalMDCTConc->nSamplesCore );
892 1035 : nBands = psychParamsCurrent->nBands;
893 : }
894 :
895 1869 : v_multc( powerSpectrum + hTonalMDCTConc->nSamplesCore, hTonalMDCTConc->secondLastBlockData.scaleFactors[nBands - 1], powerSpectrum + hTonalMDCTConc->nSamplesCore, nSamples - hTonalMDCTConc->nSamplesCore );
896 :
897 1869 : phaseDiff = hTonalMDCTConc->pTCI->phaseDiff; /* if multiple frame loss occurs use the phase from the last frame and continue rotating */
898 1869 : pCurrentPhase = hTonalMDCTConc->pTCI->phase_currentFramePredicted;
899 :
900 1869 : if ( !hTonalMDCTConc->lastBlockData.blockIsConcealed )
901 : {
902 1359 : if ( hTonalMDCTConc->secondLastBlockData.tonalConcealmentActive )
903 : {
904 75 : hTonalMDCTConc->nFramesLost += 1;
905 : }
906 : else
907 : {
908 1284 : hTonalMDCTConc->nFramesLost = 1.5;
909 : }
910 : }
911 :
912 : /* for each index group */
913 12297 : for ( i = 0; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
914 : {
915 10428 : phaseToAdd = hTonalMDCTConc->nFramesLost * phaseDiff[i];
916 :
917 : /* Move phaseToAdd to range -EVS_PI..EVS_PI */
918 32976 : while ( phaseToAdd > EVS_PI )
919 : {
920 22548 : phaseToAdd -= PI2;
921 : }
922 :
923 10428 : while ( phaseToAdd < -EVS_PI )
924 : {
925 : /* should never occur in flt - kept for safety reasons */
926 0 : phaseToAdd += PI2;
927 : }
928 :
929 83391 : for ( l = hTonalMDCTConc->pTCI->lowerIndex[i]; l <= hTonalMDCTConc->pTCI->upperIndex[i]; l++ )
930 : {
931 72963 : const float currentPhase = ( *pCurrentPhase++ ) + phaseToAdd; /* *pCurrentPhase and phaseToAdd are in range -EVS_PI..EVS_PI */
932 72963 : mdctSpectrum[l] = (float) cos( currentPhase ) * powerSpectrum[l];
933 : }
934 : }
935 : }
936 :
937 1869 : hTonalMDCTConc->nFramesLost++;
938 :
939 1869 : return;
940 : }
941 :
942 :
943 2768334 : void TonalMDCTConceal_SaveTimeSignal(
944 : TonalMDCTConcealPtr hTonalMDCTConc,
945 : float *timeSignal,
946 : const int16_t nNewSamples )
947 : {
948 2768334 : if ( nNewSamples == hTonalMDCTConc->nSamples )
949 : {
950 2720748 : assert( nNewSamples <= L_FRAME_MAX );
951 :
952 2720748 : if ( !hTonalMDCTConc->secondLastBlockData.tonalConcealmentActive )
953 : {
954 2719428 : mvr2r( hTonalMDCTConc->lastPcmOut + hTonalMDCTConc->nSamples / 2, hTonalMDCTConc->secondLastPcmOut, hTonalMDCTConc->nSamples / 2 );
955 : }
956 :
957 2720748 : mvr2r( timeSignal, hTonalMDCTConc->lastPcmOut, hTonalMDCTConc->nSamples );
958 : }
959 :
960 2768334 : return;
961 : }
962 :
963 11073 : void TonalMdctConceal_create_concealment_noise(
964 : float concealment_noise[L_FRAME48k],
965 : CPE_DEC_HANDLE hCPE,
966 : const int16_t L_frameTCX,
967 : const int16_t L_frame,
968 : const int16_t idchan,
969 : const int16_t subframe_idx,
970 : const int16_t core,
971 : const float crossfade_gain,
972 : const TONALMDCTCONC_NOISE_GEN_MODE noise_gen_mode )
973 : {
974 : STEREO_MDCT_DEC_DATA_HANDLE hStereoMdct;
975 : TonalMDCTConcealPtr hTonalMDCTConc;
976 : Decoder_State *st;
977 : HANDLE_FD_CNG_COM hFdCngCom;
978 : int16_t *rnd_c, *rnd;
979 : int16_t crossOverFreq, i, save_rnd_c, max_noise_line;
980 : float c, c_inv;
981 : float noise_shape_buffer[L_FRAME48k];
982 : int16_t inc, start_idx, stop_idx;
983 : float *cngNoiseLevelPtr;
984 : float last_scf;
985 :
986 11073 : push_wmops( "create_conc_noise" );
987 :
988 11073 : hStereoMdct = hCPE->hStereoMdct;
989 11073 : st = hCPE->hCoreCoder[idchan];
990 11073 : hTonalMDCTConc = st->hTonalMDCTConc;
991 11073 : hFdCngCom = st->hFdCngDec->hFdCngCom;
992 11073 : rnd = &hStereoMdct->noise_seeds_channels[idchan];
993 11073 : rnd_c = &hStereoMdct->noise_seed_common;
994 :
995 : /* determine start bin for IGF */
996 11073 : if ( st->igf == 0 )
997 : {
998 4176 : if ( st->narrowBand == 0 )
999 : {
1000 : /* minimum needed for output with sampling rates lower then the
1001 : nominal sampling rate */
1002 4176 : crossOverFreq = min( L_frameTCX, L_frame );
1003 : }
1004 : else
1005 : {
1006 0 : crossOverFreq = L_frameTCX;
1007 : }
1008 : }
1009 : else
1010 : {
1011 6897 : crossOverFreq = min( st->hIGFDec->infoIGFStartLine, L_frameTCX );
1012 : }
1013 :
1014 : /* for tonal mdct concealment with tonal components above the crossover frequency, conditionally raise the frequency index until which noise is generated */
1015 11073 : max_noise_line = crossOverFreq;
1016 11073 : if ( st->tonal_mdct_plc_active )
1017 : {
1018 411 : max_noise_line = max( max_noise_line, hTonalMDCTConc->pTCI->upperIndex[hTonalMDCTConc->pTCI->numIndexes - 1] + 1 );
1019 : }
1020 :
1021 : /* first lost frame is handled separately */
1022 11073 : if ( !hTonalMDCTConc->lastBlockData.blockIsConcealed )
1023 : {
1024 6174 : *rnd = 1977 + idchan;
1025 : /* will be set twice when looping over two channels, but does not matter */
1026 6174 : *rnd_c = 1979;
1027 : }
1028 :
1029 11073 : if ( crossfade_gain == 1.0f )
1030 : {
1031 : /* In first frame, noise is weighted with zero anyway, we only need the random numbers for the sign scrambling */
1032 2355387 : for ( i = 0; i < max_noise_line; i++ )
1033 : {
1034 2349213 : *rnd = own_random( rnd );
1035 2349213 : concealment_noise[i] = *rnd;
1036 : }
1037 :
1038 6174 : pop_wmops();
1039 :
1040 6174 : return;
1041 : }
1042 :
1043 4899 : save_rnd_c = *rnd_c;
1044 :
1045 4899 : c = sqrtf( hStereoMdct->lastCoh );
1046 4899 : c_inv = sqrtf( 1 - hStereoMdct->lastCoh );
1047 :
1048 : /* pre-compute the noise shape for later weighting of the noise spectra */
1049 4899 : cngNoiseLevelPtr = &hFdCngCom->cngNoiseLevel[0];
1050 4899 : inc = ( st->core > TCX_20_CORE ) ? 2 : 1;
1051 4899 : start_idx = hFdCngCom->startBand / inc;
1052 4899 : stop_idx = hFdCngCom->stopFFTbin / inc;
1053 :
1054 14673 : for ( i = 0; i < start_idx; i++ )
1055 : {
1056 9774 : noise_shape_buffer[i] = 0.0f;
1057 : }
1058 1558965 : for ( ; i < stop_idx; i++, cngNoiseLevelPtr += inc )
1059 : {
1060 1554066 : noise_shape_buffer[i] = sqrtf( *( cngNoiseLevelPtr ) );
1061 : }
1062 :
1063 4899 : last_scf = sqrtf( *( cngNoiseLevelPtr - inc ) );
1064 :
1065 306756 : for ( ; i < max_noise_line; i++ )
1066 : {
1067 301857 : noise_shape_buffer[i] = last_scf;
1068 : }
1069 :
1070 : /* fill the noise vector */
1071 4899 : hTonalMDCTConc->curr_noise_nrg = MDCT_ST_PLC_FADEOUT_MIN_NOISE_NRG;
1072 4899 : if ( noise_gen_mode == EQUAL_CORES || ( ( noise_gen_mode == TCX20_IN_0_TCX10_IN_1 && idchan == 0 ) || ( noise_gen_mode == TCX10_IN_0_TCX20_IN_1 && idchan == 1 ) ) )
1073 : {
1074 : /* current channel is TCX20 -> generate noise for "full-length" spectrum */
1075 1870596 : for ( i = 0; i < max_noise_line; i++ )
1076 : {
1077 1865697 : *rnd = own_random( rnd );
1078 1865697 : *rnd_c = own_random( rnd_c );
1079 :
1080 1865697 : concealment_noise[i] = ( c_inv * *rnd + c * *rnd_c ) * noise_shape_buffer[i];
1081 1865697 : hTonalMDCTConc->curr_noise_nrg += concealment_noise[i] * concealment_noise[i];
1082 : }
1083 : }
1084 : else /* ( ( noise_gen_mode == TCX10_IN_0_TCX20_IN_1 && idchan == 0 ) || ( noise_gen_mode == TCX20_IN_0_TCX10_IN_1 && idchan == 1 ) ) */
1085 : {
1086 : /* 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 */
1087 0 : for ( i = 0; i < max_noise_line; i++ )
1088 : {
1089 0 : *rnd = own_random( rnd );
1090 0 : *rnd_c = own_random( rnd_c );
1091 :
1092 0 : concealment_noise[i] = ( c_inv * *rnd + c * *rnd_c ) * noise_shape_buffer[i];
1093 0 : hTonalMDCTConc->curr_noise_nrg += concealment_noise[i] * concealment_noise[i];
1094 :
1095 0 : *rnd_c = own_random( rnd_c );
1096 : }
1097 : }
1098 :
1099 4899 : if ( st->tonal_mdct_plc_active )
1100 : {
1101 294 : for ( i = crossOverFreq; i < max( crossOverFreq, hTonalMDCTConc->pTCI->lowerIndex[hTonalMDCTConc->pTCI->numIndexes - 1] ); ++i )
1102 : {
1103 228 : concealment_noise[i] *= 0.0f;
1104 : }
1105 : }
1106 :
1107 : /* restore common seed
1108 : - after finishing the first channel
1109 : - after a first subframe if the current channel is TCX10 */
1110 4899 : if ( ( idchan == 0 && ( core == TCX_20 || ( core == TCX_10 && subframe_idx == 1 ) ) ) || ( core == TCX_10 && subframe_idx == 0 ) )
1111 : {
1112 2421 : *rnd_c = save_rnd_c;
1113 : }
1114 :
1115 4899 : st->seed_tcx_plc = *rnd;
1116 :
1117 4899 : pop_wmops();
1118 :
1119 4899 : return;
1120 : }
1121 :
1122 7074 : void TonalMdctConceal_whiten_noise_shape(
1123 : Decoder_State *st,
1124 : const int16_t L_frame,
1125 : const TONALMDCTCONC_NOISE_SHAPE_WHITENING_MODE whitening_mode )
1126 : {
1127 : int16_t inc, start_idx, stop_idx;
1128 : float *noiseLevelPtr, *scfs_bg, *scfs_for_shaping;
1129 : HANDLE_FD_CNG_COM hFdCngCom;
1130 : float whitenend_noise_shape[L_FRAME16k];
1131 : float scfs_int[FDNS_NPTS];
1132 : const PsychoacousticParameters *psychParams;
1133 :
1134 7074 : push_wmops( "apply_sns_on_noise_shape" );
1135 :
1136 7074 : scfs_bg = &st->hTonalMDCTConc->scaleFactorsBackground[0];
1137 7074 : psychParams = st->hTonalMDCTConc->psychParams;
1138 7074 : hFdCngCom = st->hFdCngDec->hFdCngCom;
1139 :
1140 7074 : inc = ( ( whitening_mode == ON_FIRST_LOST_FRAME ? st->core : st->last_core ) > TCX_20_CORE ) ? 2 : 1;
1141 7074 : start_idx = hFdCngCom->startBand / inc;
1142 7074 : stop_idx = L_frame / inc;
1143 7074 : noiseLevelPtr = hFdCngCom->cngNoiseLevel;
1144 :
1145 7074 : set_zero( whitenend_noise_shape, start_idx );
1146 2232279 : for ( int16_t j = start_idx; j < stop_idx; j++, noiseLevelPtr += inc )
1147 : {
1148 2225205 : whitenend_noise_shape[j] = *noiseLevelPtr;
1149 : }
1150 :
1151 7074 : if ( whitening_mode == ON_FIRST_LOST_FRAME )
1152 : {
1153 : float scf[SNS_NPTS];
1154 :
1155 1263 : sns_compute_scf( whitenend_noise_shape, psychParams, L_frame, scf );
1156 1263 : sns_interpolate_scalefactors( scfs_int, scf, ENC );
1157 1263 : sns_interpolate_scalefactors( scfs_bg, scf, DEC );
1158 1263 : scfs_for_shaping = &scfs_int[0];
1159 : }
1160 : else /* whitening_mode == ON_FIRST_GOOD_FRAME */
1161 : {
1162 5811 : scfs_for_shaping = &scfs_bg[0];
1163 : }
1164 :
1165 7074 : if ( sum_f( scfs_for_shaping, FDNS_NPTS ) > 0.0f )
1166 : {
1167 2475 : sns_shape_spectrum( whitenend_noise_shape, psychParams, scfs_for_shaping, L_frame );
1168 2475 : mvr2r( whitenend_noise_shape + start_idx, hFdCngCom->cngNoiseLevel, stop_idx - start_idx );
1169 : }
1170 : else
1171 : {
1172 4599 : set_zero( hFdCngCom->cngNoiseLevel, stop_idx - start_idx );
1173 : }
1174 :
1175 7074 : pop_wmops();
1176 7074 : }
|