blob: e56c062841536da5a323eea1d05c935495199af3 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
henrik.lundin@webrtc.org68383342012-02-03 12:33:50 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11/*
12 * This file contains the Pre-emptive Expand algorithm that is used to increase
13 * the delay by repeating a part of the audio stream.
14 */
15
16#include "dsp.h"
17
18#include "signal_processing_library.h"
19
20#include "dsp_helpfunctions.h"
21#include "neteq_error_codes.h"
22
23#define PREEMPTIVE_CORR_LEN 50
24#define PREEMPTIVE_MIN_LAG 10
25#define PREEMPTIVE_MAX_LAG 60
26#define PREEMPTIVE_DOWNSAMPLED_LEN (PREEMPTIVE_CORR_LEN + PREEMPTIVE_MAX_LAG)
27
28/* Scratch usage:
29
30 Type Name size startpos endpos
pbos@webrtc.org0946a562013-04-09 00:28:06 +000031 int16_t pw16_downSampSpeech 110 0 109
32 int32_t pw32_corr 2*50 110 209
33 int16_t pw16_corr 50 0 49
niklase@google.com470e71d2011-07-07 08:21:25 +000034
35 Total: 110+2*50
36 */
37
38#define SCRATCH_PW16_DS_SPEECH 0
39#define SCRATCH_PW32_CORR PREEMPTIVE_DOWNSAMPLED_LEN
40#define SCRATCH_PW16_CORR 0
41
42/****************************************************************************
43 * WebRtcNetEQ_PreEmptiveExpand(...)
44 *
45 * This function tries to extend the audio data by repeating one or several
46 * pitch periods. The operation is only carried out if the correlation is
47 * strong or if the signal energy is very low. The algorithm is the
48 * reciprocal of the Accelerate algorithm.
49 *
50 * Input:
51 * - inst : NetEQ DSP instance
52 * - scratchPtr : Pointer to scratch vector.
53 * - decoded : Pointer to newly decoded speech.
54 * - len : Length of decoded speech.
55 * - oldDataLen : Length of the part of decoded that has already been played out.
56 * - BGNonly : If non-zero, Pre-emptive Expand will only copy
57 * the first DEFAULT_TIME_ADJUST seconds of the
58 * input and append to the end. No signal matching is
59 * done.
60 *
61 * Output:
62 * - inst : Updated instance
63 * - outData : Pointer to a memory space where the output data
64 * should be stored. The vector must be at least
65 * min(len + 120*fs/8000, NETEQ_MAX_OUTPUT_SIZE)
66 * elements long.
67 * - pw16_len : Number of samples written to outData.
68 *
69 * Return value : 0 - Ok
70 * <0 - Error
71 */
72
73int WebRtcNetEQ_PreEmptiveExpand(DSPInst_t *inst,
74#ifdef SCRATCH
pbos@webrtc.org0946a562013-04-09 00:28:06 +000075 int16_t *pw16_scratchPtr,
niklase@google.com470e71d2011-07-07 08:21:25 +000076#endif
pbos@webrtc.org0946a562013-04-09 00:28:06 +000077 const int16_t *pw16_decoded, int len, int oldDataLen,
78 int16_t *pw16_outData, int16_t *pw16_len,
79 int16_t BGNonly)
niklase@google.com470e71d2011-07-07 08:21:25 +000080{
81
82#ifdef SCRATCH
83 /* Use scratch memory for internal temporary vectors */
pbos@webrtc.org0946a562013-04-09 00:28:06 +000084 int16_t *pw16_downSampSpeech = pw16_scratchPtr + SCRATCH_PW16_DS_SPEECH;
85 int32_t *pw32_corr = (int32_t*) (pw16_scratchPtr + SCRATCH_PW32_CORR);
86 int16_t *pw16_corr = pw16_scratchPtr + SCRATCH_PW16_CORR;
niklase@google.com470e71d2011-07-07 08:21:25 +000087#else
88 /* Allocate memory for temporary vectors */
pbos@webrtc.org0946a562013-04-09 00:28:06 +000089 int16_t pw16_downSampSpeech[PREEMPTIVE_DOWNSAMPLED_LEN];
90 int32_t pw32_corr[PREEMPTIVE_CORR_LEN];
91 int16_t pw16_corr[PREEMPTIVE_CORR_LEN];
niklase@google.com470e71d2011-07-07 08:21:25 +000092#endif
pbos@webrtc.org0946a562013-04-09 00:28:06 +000093 int16_t w16_decodedMax = 0;
94 int16_t w16_tmp = 0;
95 int16_t w16_tmp2;
96 int32_t w32_tmp;
97 int32_t w32_tmp2;
niklase@google.com470e71d2011-07-07 08:21:25 +000098
pbos@webrtc.org0946a562013-04-09 00:28:06 +000099 const int16_t w16_startLag = PREEMPTIVE_MIN_LAG;
100 const int16_t w16_endLag = PREEMPTIVE_MAX_LAG;
101 const int16_t w16_corrLen = PREEMPTIVE_CORR_LEN;
102 const int16_t *pw16_vec1, *pw16_vec2;
103 int16_t *pw16_vectmp;
104 int16_t w16_inc, w16_startfact;
105 int16_t w16_bestIndex, w16_bestVal;
106 int16_t w16_VAD = 1;
107 int16_t fsMult;
108 int16_t fsMult120;
109 int32_t w32_en1, w32_en2, w32_cc;
110 int16_t w16_en1, w16_en2;
111 int16_t w16_en1Scale, w16_en2Scale;
112 int16_t w16_sqrtEn1En2;
113 int16_t w16_bestCorr = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000114 int ok;
115
116#ifdef NETEQ_STEREO
117 MasterSlaveInfo *msInfo = inst->msInfo;
118#endif
119
120 fsMult = WebRtcNetEQ_CalcFsMult(inst->fs); /* Calculate fs/8000 */
121
122 /* Pre-calculate common multiplication with fsMult */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000123 fsMult120 = (int16_t) WEBRTC_SPL_MUL_16_16(fsMult, 120); /* 15 ms */
niklase@google.com470e71d2011-07-07 08:21:25 +0000124
125 inst->ExpandInst.w16_consecExp = 0; /* Last was not expand any more */
126
127 /*
128 * Sanity check for len variable; must be (almost) 30 ms (120*fsMult + max(bestIndex)).
129 * Also, the new part must be at least .625 ms (w16_overlap).
130 */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000131 if (len < (int16_t) WEBRTC_SPL_MUL_16_16((120 + 119), fsMult) || oldDataLen >= len
niklase@google.com470e71d2011-07-07 08:21:25 +0000132 - inst->ExpandInst.w16_overlap)
133 {
134 /* Length of decoded data too short */
135 inst->w16_mode = MODE_UNSUCCESS_PREEMPTIVE;
136 *pw16_len = len;
137
138
139 /* simply move all data from decoded to outData */
140
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000141 WEBRTC_SPL_MEMMOVE_W16(pw16_outData, pw16_decoded, (int16_t) len);
niklase@google.com470e71d2011-07-07 08:21:25 +0000142
143 return NETEQ_OTHER_ERROR;
144 }
145
146 /***********************************/
147 /* Special operations for BGN only */
148 /***********************************/
149
150 /* Check if "background noise only" flag is set */
151 if (BGNonly)
152 {
153 /* special operation for BGN only; simply insert a chunk of data */
154 w16_bestIndex = DEFAULT_TIME_ADJUST * (fsMult << 3); /* X*fs/1000 */
155
156 /* Sanity check for bestIndex */
157 if (w16_bestIndex > len)
158 { /* not good, do nothing instead */
159 inst->w16_mode = MODE_UNSUCCESS_PREEMPTIVE;
160 *pw16_len = len;
161
162
163 /* simply move all data from decoded to outData */
164
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000165 WEBRTC_SPL_MEMMOVE_W16(pw16_outData, pw16_decoded, (int16_t) len);
niklase@google.com470e71d2011-07-07 08:21:25 +0000166
167 return NETEQ_OTHER_ERROR;
168 }
169
170 /* set length parameter */
171 *pw16_len = len + w16_bestIndex;
172
173
174 /* copy to output */
175
176 WEBRTC_SPL_MEMMOVE_W16(pw16_outData, pw16_decoded, len);
177 WEBRTC_SPL_MEMCPY_W16(&pw16_outData[len], pw16_decoded, w16_bestIndex);
178
179 /* set mode */
180 inst->w16_mode = MODE_LOWEN_PREEMPTIVE;
181
182 /* update statistics */
183 inst->statInst.preemptiveLength += w16_bestIndex;
turaj@webrtc.org92d1f072013-04-15 16:52:04 +0000184 /* Short-term activity statistics. */
185 inst->activity_stats.preemptive_expand_bgn_samples += w16_bestIndex;
niklase@google.com470e71d2011-07-07 08:21:25 +0000186
187 return 0;
188 } /* end of special code for BGN mode */
189
190#ifdef NETEQ_STEREO
191
192 /* Sanity for msInfo */
193 if (msInfo == NULL)
194 {
195 /* this should not happen here */
196 return MASTER_SLAVE_ERROR;
197 }
198
199 if ((msInfo->msMode == NETEQ_MASTER) || (msInfo->msMode == NETEQ_MONO))
200 {
201 /* Find correlation lag only for non-slave instances */
202
203#endif
204
205 /****************************************************************/
206 /* Find the strongest correlation lag by downsampling to 4 kHz, */
207 /* calculating correlation for downsampled signal and finding */
208 /* the strongest correlation peak. */
209 /****************************************************************/
210
211 /* find maximum absolute value */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000212 w16_decodedMax = WebRtcSpl_MaxAbsValueW16(pw16_decoded, (int16_t) len);
niklase@google.com470e71d2011-07-07 08:21:25 +0000213
214 /* downsample the decoded speech to 4 kHz */
215 ok = WebRtcNetEQ_DownSampleTo4kHz(pw16_decoded, len, inst->fs, pw16_downSampSpeech,
216 PREEMPTIVE_DOWNSAMPLED_LEN, 1 /* compensate delay*/);
217 if (ok != 0)
218 {
219 /* error */
220 inst->w16_mode = MODE_UNSUCCESS_PREEMPTIVE;
221 *pw16_len = len;
222
223
224 /* simply move all data from decoded to outData */
225
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000226 WEBRTC_SPL_MEMMOVE_W16(pw16_outData, pw16_decoded, (int16_t) len);
niklase@google.com470e71d2011-07-07 08:21:25 +0000227
228 return NETEQ_OTHER_ERROR;
229 }
230
231 /*
232 * Set scaling factor for cross correlation to protect against
233 * overflow (log2(50) => 6)
234 */
235 w16_tmp = 6 - WebRtcSpl_NormW32(WEBRTC_SPL_MUL_16_16(w16_decodedMax, w16_decodedMax));
236 w16_tmp = WEBRTC_SPL_MAX(0, w16_tmp);
237
238 /* Perform correlation from lag 10 to lag 60 in 4 kHz domain */WebRtcNetEQ_CrossCorr(
239 pw32_corr, &pw16_downSampSpeech[w16_endLag],
240 &pw16_downSampSpeech[w16_endLag - w16_startLag], w16_corrLen,
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000241 (int16_t) (w16_endLag - w16_startLag), w16_tmp, -1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000242
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000243 /* Normalize correlation to 14 bits and put in a int16_t vector */
niklase@google.com470e71d2011-07-07 08:21:25 +0000244 w32_tmp = WebRtcSpl_MaxAbsValueW32(pw32_corr, w16_corrLen);
245 w16_tmp = 17 - WebRtcSpl_NormW32(w32_tmp);
246 w16_tmp = WEBRTC_SPL_MAX(0, w16_tmp);
247
248 WebRtcSpl_VectorBitShiftW32ToW16(pw16_corr, w16_corrLen, pw32_corr, w16_tmp);
249
250 /* Find limits for peak finding, in order to avoid overful NetEQ algorithm buffer. */
251 /* Calculate difference between MAX_OUTPUT_SIZE and len in 4 kHz domain. */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000252 w16_tmp = WebRtcSpl_DivW32W16ResW16((int32_t) (NETEQ_MAX_OUTPUT_SIZE - len),
253 (int16_t) (fsMult << 1)) - w16_startLag;
niklase@google.com470e71d2011-07-07 08:21:25 +0000254 w16_tmp = WEBRTC_SPL_MIN(w16_corrLen, w16_tmp); /* no more than corrLen = 50 */
255
256#ifdef NETEQ_STEREO
257 } /* end if (msInfo->msMode != NETEQ_SLAVE) */
258
259 if ((msInfo->msMode == NETEQ_MASTER) || (msInfo->msMode == NETEQ_MONO))
260 {
261 /* Find the strongest correlation peak by using the parabolic fit method */
262 WebRtcNetEQ_PeakDetection(pw16_corr, w16_tmp, 1, fsMult, &w16_bestIndex, &w16_bestVal);
263 /* 0 <= bestIndex <= (2*w16_tmp - 1)*fsMult <= (2*corrLen - 1)*fsMult = 99*fsMult */
264
265 /* Compensate bestIndex for displaced starting position */
266 w16_bestIndex = w16_bestIndex + w16_startLag * WEBRTC_SPL_LSHIFT_W16(fsMult, 1);
267 /* 20*fsMult <= bestIndex <= 119*fsMult */
268
269 msInfo->bestIndex = w16_bestIndex;
270 }
271 else if (msInfo->msMode == NETEQ_SLAVE)
272 {
273 if (msInfo->extraInfo == PE_EXP_FAIL)
274 {
275 /* Master has signaled an unsuccessful preemptive expand */
276 w16_bestIndex = 0;
277 }
278 else
279 {
280 /* Get best index from master */
281 w16_bestIndex = msInfo->bestIndex;
282 }
283 }
284 else
285 {
286 /* Invalid mode */
287 return (MASTER_SLAVE_ERROR);
288 }
289
290#else /* NETEQ_STEREO */
291
292 /* Find the strongest correlation peak by using the parabolic fit method */
293 WebRtcNetEQ_PeakDetection(pw16_corr, w16_tmp, 1, fsMult, &w16_bestIndex, &w16_bestVal);
294 /* 0 <= bestIndex <= (2*w16_tmp - 1)*fsMult <= (2*corrLen - 1)*fsMult = 99*fsMult */
295
296 /* Compensate bestIndex for displaced starting position */
297 w16_bestIndex = w16_bestIndex + w16_startLag * WEBRTC_SPL_LSHIFT_W16(fsMult, 1);
298 /* 20*fsMult <= bestIndex <= 119*fsMult */
299
300#endif /* NETEQ_STEREO */
301
302#ifdef NETEQ_STEREO
303
304 if ((msInfo->msMode == NETEQ_MASTER) || (msInfo->msMode == NETEQ_MONO))
305 {
306 /* Calculate correlation only for non-slave instances */
307
308#endif /* NETEQ_STEREO */
309
310 /*****************************************************/
311 /* Calculate correlation bestCorr for the found lag. */
312 /* Also do a simple VAD decision. */
313 /*****************************************************/
314
315 /*
316 * Calculate scaling to ensure that bestIndex samples can be square-summed
317 * without overflowing
318 */
319 w16_tmp = (31
320 - WebRtcSpl_NormW32(WEBRTC_SPL_MUL_16_16(w16_decodedMax, w16_decodedMax)));
321 w16_tmp += (31 - WebRtcSpl_NormW32(w16_bestIndex));
322 w16_tmp -= 31;
323 w16_tmp = WEBRTC_SPL_MAX(0, w16_tmp);
324
325 /* vec1 starts at 15 ms minus one pitch period */
326 pw16_vec1 = &pw16_decoded[fsMult120 - w16_bestIndex];
327 /* vec2 start at 15 ms */
328 pw16_vec2 = &pw16_decoded[fsMult120];
329
330 /* Calculate energies for vec1 and vec2 */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000331 w32_en1 = WebRtcNetEQ_DotW16W16((int16_t*) pw16_vec1,
332 (int16_t*) pw16_vec1, w16_bestIndex, w16_tmp);
333 w32_en2 = WebRtcNetEQ_DotW16W16((int16_t*) pw16_vec2,
334 (int16_t*) pw16_vec2, w16_bestIndex, w16_tmp);
niklase@google.com470e71d2011-07-07 08:21:25 +0000335
336 /* Calculate cross-correlation at the found lag */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000337 w32_cc = WebRtcNetEQ_DotW16W16((int16_t*) pw16_vec1, (int16_t*) pw16_vec2,
niklase@google.com470e71d2011-07-07 08:21:25 +0000338 w16_bestIndex, w16_tmp);
339
340 /* Check VAD constraint
341 ((en1+en2)/(2*bestIndex)) <= 8*inst->BGNInst.energy */
342 w32_tmp = WEBRTC_SPL_RSHIFT_W32(w32_en1 + w32_en2, 4); /* (en1+en2)/(2*8) */
343 if (inst->BGNInst.w16_initialized == 1)
344 {
345 w32_tmp2 = inst->BGNInst.w32_energy;
346 }
347 else
348 {
349 /* if BGN parameters have not been estimated, use a fixed threshold */
350 w32_tmp2 = 75000;
351 }
352 w16_tmp2 = 16 - WebRtcSpl_NormW32(w32_tmp2);
353 w16_tmp2 = WEBRTC_SPL_MAX(0, w16_tmp2);
354 w32_tmp = WEBRTC_SPL_RSHIFT_W32(w32_tmp, w16_tmp2);
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000355 w16_tmp2 = (int16_t) WEBRTC_SPL_RSHIFT_W32(w32_tmp2, w16_tmp2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000356 w32_tmp2 = WEBRTC_SPL_MUL_16_16(w16_bestIndex, w16_tmp2);
357
358 /* Scale w32_tmp properly before comparing with w32_tmp2 */
359 /* (w16_tmp is scaling before energy calculation, thus 2*w16_tmp) */
360 if (WebRtcSpl_NormW32(w32_tmp) < WEBRTC_SPL_LSHIFT_W32(w16_tmp,1))
361 {
362 /* Cannot scale only w32_tmp, must scale w32_temp2 too */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000363 int16_t tempshift = WebRtcSpl_NormW32(w32_tmp);
niklase@google.com470e71d2011-07-07 08:21:25 +0000364 w32_tmp = WEBRTC_SPL_LSHIFT_W32(w32_tmp, tempshift);
365 w32_tmp2 = WEBRTC_SPL_RSHIFT_W32(w32_tmp2,
366 WEBRTC_SPL_LSHIFT_W32(w16_tmp,1) - tempshift);
367 }
368 else
369 {
370 w32_tmp = WEBRTC_SPL_LSHIFT_W32(w32_tmp,
371 WEBRTC_SPL_LSHIFT_W32(w16_tmp,1));
372 }
373
374 if (w32_tmp <= w32_tmp2) /*((en1+en2)/(2*bestIndex)) <= 8*inst->BGNInst.energy */
375 {
376 /* The signal seems to be passive speech */
377 w16_VAD = 0;
378 w16_bestCorr = 0; /* Correlation does not matter */
379
380 /* For low energy expansion, the new data can be less than 15 ms,
381 but we must ensure that bestIndex is not larger than the new data. */
382 w16_bestIndex = WEBRTC_SPL_MIN( w16_bestIndex, len - oldDataLen );
383 }
384 else
385 {
386 /* The signal is active speech */
387 w16_VAD = 1;
388
389 /* Calculate correlation (cc/sqrt(en1*en2)) */
390
391 /* Start with calculating scale values */
392 w16_en1Scale = 16 - WebRtcSpl_NormW32(w32_en1);
393 w16_en1Scale = WEBRTC_SPL_MAX(0, w16_en1Scale);
394 w16_en2Scale = 16 - WebRtcSpl_NormW32(w32_en2);
395 w16_en2Scale = WEBRTC_SPL_MAX(0, w16_en2Scale);
396
397 /* Make sure total scaling is even (to simplify scale factor after sqrt) */
398 if ((w16_en1Scale + w16_en2Scale) & 1)
399 {
400 w16_en1Scale += 1;
401 }
402
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000403 /* Convert energies to int16_t */
404 w16_en1 = (int16_t) WEBRTC_SPL_RSHIFT_W32(w32_en1, w16_en1Scale);
405 w16_en2 = (int16_t) WEBRTC_SPL_RSHIFT_W32(w32_en2, w16_en2Scale);
niklase@google.com470e71d2011-07-07 08:21:25 +0000406
407 /* Calculate energy product */
408 w32_tmp = WEBRTC_SPL_MUL_16_16(w16_en1, w16_en2);
409
410 /* Calculate square-root of energy product */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000411 w16_sqrtEn1En2 = (int16_t) WebRtcSpl_SqrtFloor(w32_tmp);
niklase@google.com470e71d2011-07-07 08:21:25 +0000412
413 /* Calculate cc/sqrt(en1*en2) in Q14 */
414 w16_tmp = 14 - ((w16_en1Scale + w16_en2Scale) >> 1);
415 w32_cc = WEBRTC_SPL_SHIFT_W32(w32_cc, w16_tmp);
416 w32_cc = WEBRTC_SPL_MAX(0, w32_cc); /* Don't divide with negative number */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000417 w16_bestCorr = (int16_t) WebRtcSpl_DivW32W16(w32_cc, w16_sqrtEn1En2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000418 w16_bestCorr = WEBRTC_SPL_MIN(16384, w16_bestCorr); /* set maximum to 1.0 */
419 }
420
421#ifdef NETEQ_STEREO
422
423 } /* end if (msInfo->msMode != NETEQ_SLAVE) */
424
425#endif /* NETEQ_STEREO */
426
427 /*******************************************************/
428 /* Check preemptive expand criteria and insert samples */
429 /*******************************************************/
430
431 /* Check for strong correlation (>0.9) and at least 15 ms new data,
432 or passive speech */
433#ifdef NETEQ_STEREO
434 if (((((w16_bestCorr > 14746) && (oldDataLen <= fsMult120)) || (w16_VAD == 0))
435 && (msInfo->msMode != NETEQ_SLAVE)) || ((msInfo->msMode == NETEQ_SLAVE)
436 && (msInfo->extraInfo != PE_EXP_FAIL)))
437#else
438 if (((w16_bestCorr > 14746) && (oldDataLen <= fsMult120))
439 || (w16_VAD == 0))
440#endif
441 {
442 /* Do expand operation by overlap add */
443
444 /* Set length of the first part, not to be modified */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000445 int16_t w16_startIndex = WEBRTC_SPL_MAX(oldDataLen, fsMult120);
niklase@google.com470e71d2011-07-07 08:21:25 +0000446
447 /*
448 * Calculate cross-fading slope so that the fading factor goes from
449 * 1 (16384 in Q14) to 0 in one pitch period (bestIndex).
450 */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000451 w16_inc = (int16_t) WebRtcSpl_DivW32W16((int32_t) 16384,
452 (int16_t) (w16_bestIndex + 1)); /* in Q14 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000453
454 /* Initiate fading factor */
455 w16_startfact = 16384 - w16_inc;
456
457 /* vec1 starts at 15 ms minus one pitch period */
458 pw16_vec1 = &pw16_decoded[w16_startIndex - w16_bestIndex];
459 /* vec2 start at 15 ms */
460 pw16_vec2 = &pw16_decoded[w16_startIndex];
461
462
463 /* Copy unmodified part [0 to 15 ms] */
464
465 WEBRTC_SPL_MEMMOVE_W16(pw16_outData, pw16_decoded, w16_startIndex);
466
467 /* Generate interpolated part of length bestIndex (1 pitch period) */
468 pw16_vectmp = pw16_outData + w16_startIndex;
469 /* Reuse mixing function from Expand */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000470 WebRtcNetEQ_MixVoiceUnvoice(pw16_vectmp, (int16_t*) pw16_vec2,
471 (int16_t*) pw16_vec1, &w16_startfact, w16_inc, w16_bestIndex);
niklase@google.com470e71d2011-07-07 08:21:25 +0000472
473 /* Move the last part (also unmodified) */
474 /* Take from decoded at 15 ms */
475 pw16_vec2 = &pw16_decoded[w16_startIndex];
476 WEBRTC_SPL_MEMMOVE_W16(&pw16_outData[w16_startIndex + w16_bestIndex], pw16_vec2,
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000477 (int16_t) (len - w16_startIndex));
niklase@google.com470e71d2011-07-07 08:21:25 +0000478
479 /* Set the mode flag */
480 if (w16_VAD)
481 {
482 inst->w16_mode = MODE_SUCCESS_PREEMPTIVE;
483 }
484 else
485 {
486 inst->w16_mode = MODE_LOWEN_PREEMPTIVE;
487 }
488
489 /* Calculate resulting length = original length + pitch period */
490 *pw16_len = len + w16_bestIndex;
491
492 /* Update in-call statistics */
493 inst->statInst.preemptiveLength += w16_bestIndex;
turaj@webrtc.org92d1f072013-04-15 16:52:04 +0000494 /* Short-term activity statistics. */
495 inst->activity_stats.preemptive_expand_normal_samples += w16_bestIndex;
niklase@google.com470e71d2011-07-07 08:21:25 +0000496 return 0;
497 }
498 else
499 {
500 /* Preemptive Expand not allowed */
501
502#ifdef NETEQ_STEREO
503 /* Signal to slave(s) that this was unsuccessful */
504 if (msInfo->msMode == NETEQ_MASTER)
505 {
506 msInfo->extraInfo = PE_EXP_FAIL;
507 }
508#endif
509
510 /* Set mode flag to unsuccessful preemptive expand */
511 inst->w16_mode = MODE_UNSUCCESS_PREEMPTIVE;
512
513 /* Length is unmodified */
514 *pw16_len = len;
515
516
517 /* Simply move all data from decoded to outData */
518
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000519 WEBRTC_SPL_MEMMOVE_W16(pw16_outData, pw16_decoded, (int16_t) len);
niklase@google.com470e71d2011-07-07 08:21:25 +0000520
521 return 0;
522 }
523}
524
525#undef SCRATCH_PW16_DS_SPEECH
526#undef SCRATCH_PW32_CORR
527#undef SCRATCH_PW16_CORR