blob: 172a171ada82dce287068b167e4e58e161b0a66d [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;
184
185 return 0;
186 } /* end of special code for BGN mode */
187
188#ifdef NETEQ_STEREO
189
190 /* Sanity for msInfo */
191 if (msInfo == NULL)
192 {
193 /* this should not happen here */
194 return MASTER_SLAVE_ERROR;
195 }
196
197 if ((msInfo->msMode == NETEQ_MASTER) || (msInfo->msMode == NETEQ_MONO))
198 {
199 /* Find correlation lag only for non-slave instances */
200
201#endif
202
203 /****************************************************************/
204 /* Find the strongest correlation lag by downsampling to 4 kHz, */
205 /* calculating correlation for downsampled signal and finding */
206 /* the strongest correlation peak. */
207 /****************************************************************/
208
209 /* find maximum absolute value */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000210 w16_decodedMax = WebRtcSpl_MaxAbsValueW16(pw16_decoded, (int16_t) len);
niklase@google.com470e71d2011-07-07 08:21:25 +0000211
212 /* downsample the decoded speech to 4 kHz */
213 ok = WebRtcNetEQ_DownSampleTo4kHz(pw16_decoded, len, inst->fs, pw16_downSampSpeech,
214 PREEMPTIVE_DOWNSAMPLED_LEN, 1 /* compensate delay*/);
215 if (ok != 0)
216 {
217 /* error */
218 inst->w16_mode = MODE_UNSUCCESS_PREEMPTIVE;
219 *pw16_len = len;
220
221
222 /* simply move all data from decoded to outData */
223
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000224 WEBRTC_SPL_MEMMOVE_W16(pw16_outData, pw16_decoded, (int16_t) len);
niklase@google.com470e71d2011-07-07 08:21:25 +0000225
226 return NETEQ_OTHER_ERROR;
227 }
228
229 /*
230 * Set scaling factor for cross correlation to protect against
231 * overflow (log2(50) => 6)
232 */
233 w16_tmp = 6 - WebRtcSpl_NormW32(WEBRTC_SPL_MUL_16_16(w16_decodedMax, w16_decodedMax));
234 w16_tmp = WEBRTC_SPL_MAX(0, w16_tmp);
235
236 /* Perform correlation from lag 10 to lag 60 in 4 kHz domain */WebRtcNetEQ_CrossCorr(
237 pw32_corr, &pw16_downSampSpeech[w16_endLag],
238 &pw16_downSampSpeech[w16_endLag - w16_startLag], w16_corrLen,
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000239 (int16_t) (w16_endLag - w16_startLag), w16_tmp, -1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000240
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000241 /* Normalize correlation to 14 bits and put in a int16_t vector */
niklase@google.com470e71d2011-07-07 08:21:25 +0000242 w32_tmp = WebRtcSpl_MaxAbsValueW32(pw32_corr, w16_corrLen);
243 w16_tmp = 17 - WebRtcSpl_NormW32(w32_tmp);
244 w16_tmp = WEBRTC_SPL_MAX(0, w16_tmp);
245
246 WebRtcSpl_VectorBitShiftW32ToW16(pw16_corr, w16_corrLen, pw32_corr, w16_tmp);
247
248 /* Find limits for peak finding, in order to avoid overful NetEQ algorithm buffer. */
249 /* Calculate difference between MAX_OUTPUT_SIZE and len in 4 kHz domain. */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000250 w16_tmp = WebRtcSpl_DivW32W16ResW16((int32_t) (NETEQ_MAX_OUTPUT_SIZE - len),
251 (int16_t) (fsMult << 1)) - w16_startLag;
niklase@google.com470e71d2011-07-07 08:21:25 +0000252 w16_tmp = WEBRTC_SPL_MIN(w16_corrLen, w16_tmp); /* no more than corrLen = 50 */
253
254#ifdef NETEQ_STEREO
255 } /* end if (msInfo->msMode != NETEQ_SLAVE) */
256
257 if ((msInfo->msMode == NETEQ_MASTER) || (msInfo->msMode == NETEQ_MONO))
258 {
259 /* Find the strongest correlation peak by using the parabolic fit method */
260 WebRtcNetEQ_PeakDetection(pw16_corr, w16_tmp, 1, fsMult, &w16_bestIndex, &w16_bestVal);
261 /* 0 <= bestIndex <= (2*w16_tmp - 1)*fsMult <= (2*corrLen - 1)*fsMult = 99*fsMult */
262
263 /* Compensate bestIndex for displaced starting position */
264 w16_bestIndex = w16_bestIndex + w16_startLag * WEBRTC_SPL_LSHIFT_W16(fsMult, 1);
265 /* 20*fsMult <= bestIndex <= 119*fsMult */
266
267 msInfo->bestIndex = w16_bestIndex;
268 }
269 else if (msInfo->msMode == NETEQ_SLAVE)
270 {
271 if (msInfo->extraInfo == PE_EXP_FAIL)
272 {
273 /* Master has signaled an unsuccessful preemptive expand */
274 w16_bestIndex = 0;
275 }
276 else
277 {
278 /* Get best index from master */
279 w16_bestIndex = msInfo->bestIndex;
280 }
281 }
282 else
283 {
284 /* Invalid mode */
285 return (MASTER_SLAVE_ERROR);
286 }
287
288#else /* NETEQ_STEREO */
289
290 /* Find the strongest correlation peak by using the parabolic fit method */
291 WebRtcNetEQ_PeakDetection(pw16_corr, w16_tmp, 1, fsMult, &w16_bestIndex, &w16_bestVal);
292 /* 0 <= bestIndex <= (2*w16_tmp - 1)*fsMult <= (2*corrLen - 1)*fsMult = 99*fsMult */
293
294 /* Compensate bestIndex for displaced starting position */
295 w16_bestIndex = w16_bestIndex + w16_startLag * WEBRTC_SPL_LSHIFT_W16(fsMult, 1);
296 /* 20*fsMult <= bestIndex <= 119*fsMult */
297
298#endif /* NETEQ_STEREO */
299
300#ifdef NETEQ_STEREO
301
302 if ((msInfo->msMode == NETEQ_MASTER) || (msInfo->msMode == NETEQ_MONO))
303 {
304 /* Calculate correlation only for non-slave instances */
305
306#endif /* NETEQ_STEREO */
307
308 /*****************************************************/
309 /* Calculate correlation bestCorr for the found lag. */
310 /* Also do a simple VAD decision. */
311 /*****************************************************/
312
313 /*
314 * Calculate scaling to ensure that bestIndex samples can be square-summed
315 * without overflowing
316 */
317 w16_tmp = (31
318 - WebRtcSpl_NormW32(WEBRTC_SPL_MUL_16_16(w16_decodedMax, w16_decodedMax)));
319 w16_tmp += (31 - WebRtcSpl_NormW32(w16_bestIndex));
320 w16_tmp -= 31;
321 w16_tmp = WEBRTC_SPL_MAX(0, w16_tmp);
322
323 /* vec1 starts at 15 ms minus one pitch period */
324 pw16_vec1 = &pw16_decoded[fsMult120 - w16_bestIndex];
325 /* vec2 start at 15 ms */
326 pw16_vec2 = &pw16_decoded[fsMult120];
327
328 /* Calculate energies for vec1 and vec2 */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000329 w32_en1 = WebRtcNetEQ_DotW16W16((int16_t*) pw16_vec1,
330 (int16_t*) pw16_vec1, w16_bestIndex, w16_tmp);
331 w32_en2 = WebRtcNetEQ_DotW16W16((int16_t*) pw16_vec2,
332 (int16_t*) pw16_vec2, w16_bestIndex, w16_tmp);
niklase@google.com470e71d2011-07-07 08:21:25 +0000333
334 /* Calculate cross-correlation at the found lag */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000335 w32_cc = WebRtcNetEQ_DotW16W16((int16_t*) pw16_vec1, (int16_t*) pw16_vec2,
niklase@google.com470e71d2011-07-07 08:21:25 +0000336 w16_bestIndex, w16_tmp);
337
338 /* Check VAD constraint
339 ((en1+en2)/(2*bestIndex)) <= 8*inst->BGNInst.energy */
340 w32_tmp = WEBRTC_SPL_RSHIFT_W32(w32_en1 + w32_en2, 4); /* (en1+en2)/(2*8) */
341 if (inst->BGNInst.w16_initialized == 1)
342 {
343 w32_tmp2 = inst->BGNInst.w32_energy;
344 }
345 else
346 {
347 /* if BGN parameters have not been estimated, use a fixed threshold */
348 w32_tmp2 = 75000;
349 }
350 w16_tmp2 = 16 - WebRtcSpl_NormW32(w32_tmp2);
351 w16_tmp2 = WEBRTC_SPL_MAX(0, w16_tmp2);
352 w32_tmp = WEBRTC_SPL_RSHIFT_W32(w32_tmp, w16_tmp2);
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000353 w16_tmp2 = (int16_t) WEBRTC_SPL_RSHIFT_W32(w32_tmp2, w16_tmp2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000354 w32_tmp2 = WEBRTC_SPL_MUL_16_16(w16_bestIndex, w16_tmp2);
355
356 /* Scale w32_tmp properly before comparing with w32_tmp2 */
357 /* (w16_tmp is scaling before energy calculation, thus 2*w16_tmp) */
358 if (WebRtcSpl_NormW32(w32_tmp) < WEBRTC_SPL_LSHIFT_W32(w16_tmp,1))
359 {
360 /* Cannot scale only w32_tmp, must scale w32_temp2 too */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000361 int16_t tempshift = WebRtcSpl_NormW32(w32_tmp);
niklase@google.com470e71d2011-07-07 08:21:25 +0000362 w32_tmp = WEBRTC_SPL_LSHIFT_W32(w32_tmp, tempshift);
363 w32_tmp2 = WEBRTC_SPL_RSHIFT_W32(w32_tmp2,
364 WEBRTC_SPL_LSHIFT_W32(w16_tmp,1) - tempshift);
365 }
366 else
367 {
368 w32_tmp = WEBRTC_SPL_LSHIFT_W32(w32_tmp,
369 WEBRTC_SPL_LSHIFT_W32(w16_tmp,1));
370 }
371
372 if (w32_tmp <= w32_tmp2) /*((en1+en2)/(2*bestIndex)) <= 8*inst->BGNInst.energy */
373 {
374 /* The signal seems to be passive speech */
375 w16_VAD = 0;
376 w16_bestCorr = 0; /* Correlation does not matter */
377
378 /* For low energy expansion, the new data can be less than 15 ms,
379 but we must ensure that bestIndex is not larger than the new data. */
380 w16_bestIndex = WEBRTC_SPL_MIN( w16_bestIndex, len - oldDataLen );
381 }
382 else
383 {
384 /* The signal is active speech */
385 w16_VAD = 1;
386
387 /* Calculate correlation (cc/sqrt(en1*en2)) */
388
389 /* Start with calculating scale values */
390 w16_en1Scale = 16 - WebRtcSpl_NormW32(w32_en1);
391 w16_en1Scale = WEBRTC_SPL_MAX(0, w16_en1Scale);
392 w16_en2Scale = 16 - WebRtcSpl_NormW32(w32_en2);
393 w16_en2Scale = WEBRTC_SPL_MAX(0, w16_en2Scale);
394
395 /* Make sure total scaling is even (to simplify scale factor after sqrt) */
396 if ((w16_en1Scale + w16_en2Scale) & 1)
397 {
398 w16_en1Scale += 1;
399 }
400
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000401 /* Convert energies to int16_t */
402 w16_en1 = (int16_t) WEBRTC_SPL_RSHIFT_W32(w32_en1, w16_en1Scale);
403 w16_en2 = (int16_t) WEBRTC_SPL_RSHIFT_W32(w32_en2, w16_en2Scale);
niklase@google.com470e71d2011-07-07 08:21:25 +0000404
405 /* Calculate energy product */
406 w32_tmp = WEBRTC_SPL_MUL_16_16(w16_en1, w16_en2);
407
408 /* Calculate square-root of energy product */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000409 w16_sqrtEn1En2 = (int16_t) WebRtcSpl_SqrtFloor(w32_tmp);
niklase@google.com470e71d2011-07-07 08:21:25 +0000410
411 /* Calculate cc/sqrt(en1*en2) in Q14 */
412 w16_tmp = 14 - ((w16_en1Scale + w16_en2Scale) >> 1);
413 w32_cc = WEBRTC_SPL_SHIFT_W32(w32_cc, w16_tmp);
414 w32_cc = WEBRTC_SPL_MAX(0, w32_cc); /* Don't divide with negative number */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000415 w16_bestCorr = (int16_t) WebRtcSpl_DivW32W16(w32_cc, w16_sqrtEn1En2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000416 w16_bestCorr = WEBRTC_SPL_MIN(16384, w16_bestCorr); /* set maximum to 1.0 */
417 }
418
419#ifdef NETEQ_STEREO
420
421 } /* end if (msInfo->msMode != NETEQ_SLAVE) */
422
423#endif /* NETEQ_STEREO */
424
425 /*******************************************************/
426 /* Check preemptive expand criteria and insert samples */
427 /*******************************************************/
428
429 /* Check for strong correlation (>0.9) and at least 15 ms new data,
430 or passive speech */
431#ifdef NETEQ_STEREO
432 if (((((w16_bestCorr > 14746) && (oldDataLen <= fsMult120)) || (w16_VAD == 0))
433 && (msInfo->msMode != NETEQ_SLAVE)) || ((msInfo->msMode == NETEQ_SLAVE)
434 && (msInfo->extraInfo != PE_EXP_FAIL)))
435#else
436 if (((w16_bestCorr > 14746) && (oldDataLen <= fsMult120))
437 || (w16_VAD == 0))
438#endif
439 {
440 /* Do expand operation by overlap add */
441
442 /* Set length of the first part, not to be modified */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000443 int16_t w16_startIndex = WEBRTC_SPL_MAX(oldDataLen, fsMult120);
niklase@google.com470e71d2011-07-07 08:21:25 +0000444
445 /*
446 * Calculate cross-fading slope so that the fading factor goes from
447 * 1 (16384 in Q14) to 0 in one pitch period (bestIndex).
448 */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000449 w16_inc = (int16_t) WebRtcSpl_DivW32W16((int32_t) 16384,
450 (int16_t) (w16_bestIndex + 1)); /* in Q14 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000451
452 /* Initiate fading factor */
453 w16_startfact = 16384 - w16_inc;
454
455 /* vec1 starts at 15 ms minus one pitch period */
456 pw16_vec1 = &pw16_decoded[w16_startIndex - w16_bestIndex];
457 /* vec2 start at 15 ms */
458 pw16_vec2 = &pw16_decoded[w16_startIndex];
459
460
461 /* Copy unmodified part [0 to 15 ms] */
462
463 WEBRTC_SPL_MEMMOVE_W16(pw16_outData, pw16_decoded, w16_startIndex);
464
465 /* Generate interpolated part of length bestIndex (1 pitch period) */
466 pw16_vectmp = pw16_outData + w16_startIndex;
467 /* Reuse mixing function from Expand */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000468 WebRtcNetEQ_MixVoiceUnvoice(pw16_vectmp, (int16_t*) pw16_vec2,
469 (int16_t*) pw16_vec1, &w16_startfact, w16_inc, w16_bestIndex);
niklase@google.com470e71d2011-07-07 08:21:25 +0000470
471 /* Move the last part (also unmodified) */
472 /* Take from decoded at 15 ms */
473 pw16_vec2 = &pw16_decoded[w16_startIndex];
474 WEBRTC_SPL_MEMMOVE_W16(&pw16_outData[w16_startIndex + w16_bestIndex], pw16_vec2,
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000475 (int16_t) (len - w16_startIndex));
niklase@google.com470e71d2011-07-07 08:21:25 +0000476
477 /* Set the mode flag */
478 if (w16_VAD)
479 {
480 inst->w16_mode = MODE_SUCCESS_PREEMPTIVE;
481 }
482 else
483 {
484 inst->w16_mode = MODE_LOWEN_PREEMPTIVE;
485 }
486
487 /* Calculate resulting length = original length + pitch period */
488 *pw16_len = len + w16_bestIndex;
489
490 /* Update in-call statistics */
491 inst->statInst.preemptiveLength += w16_bestIndex;
492
493 return 0;
494 }
495 else
496 {
497 /* Preemptive Expand not allowed */
498
499#ifdef NETEQ_STEREO
500 /* Signal to slave(s) that this was unsuccessful */
501 if (msInfo->msMode == NETEQ_MASTER)
502 {
503 msInfo->extraInfo = PE_EXP_FAIL;
504 }
505#endif
506
507 /* Set mode flag to unsuccessful preemptive expand */
508 inst->w16_mode = MODE_UNSUCCESS_PREEMPTIVE;
509
510 /* Length is unmodified */
511 *pw16_len = len;
512
513
514 /* Simply move all data from decoded to outData */
515
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000516 WEBRTC_SPL_MEMMOVE_W16(pw16_outData, pw16_decoded, (int16_t) len);
niklase@google.com470e71d2011-07-07 08:21:25 +0000517
518 return 0;
519 }
520}
521
522#undef SCRATCH_PW16_DS_SPEECH
523#undef SCRATCH_PW32_CORR
524#undef SCRATCH_PW16_CORR