blob: 78da2c7c7db40aaf6b4780c35c731ed3a1b62567 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
henrik.lundin@webrtc.orgdd478e22012-01-31 13:12:41 +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 is the function to merge a new packet with expanded data after a packet loss.
13 */
14
15#include "dsp.h"
16
17#include "signal_processing_library.h"
18
19#include "dsp_helpfunctions.h"
20#include "neteq_error_codes.h"
21
22/****************************************************************************
23 * WebRtcNetEQ_Merge(...)
24 *
25 * This function...
26 *
27 * Input:
28 * - inst : NetEQ DSP instance
29 * - scratchPtr : Pointer to scratch vector.
30 * - decoded : Pointer to new decoded speech.
31 * - len : Number of samples in pw16_decoded.
32 *
33 *
34 * Output:
35 * - inst : Updated user information
36 * - outData : Pointer to a memory space where the output data
37 * should be stored
38 * - pw16_len : Number of samples written to pw16_outData
39 *
40 * Return value : 0 - Ok
41 * <0 - Error
42 */
43
44/* Scratch usage:
45
46 Type Name size startpos endpos
pbos@webrtc.org0946a562013-04-09 00:28:06 +000047 int16_t pw16_expanded 210*fs/8000 0 209*fs/8000
48 int16_t pw16_expandedLB 100 210*fs/8000 99+210*fs/8000
49 int16_t pw16_decodedLB 40 100+210*fs/8000 139+210*fs/8000
50 int32_t pw32_corr 2*60 140+210*fs/8000 260+210*fs/8000
51 int16_t pw16_corrVec 68 210*fs/8000 67+210*fs/8000
niklase@google.com470e71d2011-07-07 08:21:25 +000052
53 [gap in scratch vector]
54
55 func WebRtcNetEQ_Expand 40+370*fs/8000 126*fs/8000 39+496*fs/8000
56
57 Total: 40+496*fs/8000
58 */
59
60#define SCRATCH_pw16_expanded 0
61#if (defined(NETEQ_48KHZ_WIDEBAND))
62#define SCRATCH_pw16_expandedLB 1260
63#define SCRATCH_pw16_decodedLB 1360
64#define SCRATCH_pw32_corr 1400
65#define SCRATCH_pw16_corrVec 1260
66#define SCRATCH_NETEQ_EXPAND 756
67#elif (defined(NETEQ_32KHZ_WIDEBAND))
68#define SCRATCH_pw16_expandedLB 840
69#define SCRATCH_pw16_decodedLB 940
70#define SCRATCH_pw32_corr 980
71#define SCRATCH_pw16_corrVec 840
72#define SCRATCH_NETEQ_EXPAND 504
73#elif (defined(NETEQ_WIDEBAND))
74#define SCRATCH_pw16_expandedLB 420
75#define SCRATCH_pw16_decodedLB 520
76#define SCRATCH_pw32_corr 560
77#define SCRATCH_pw16_corrVec 420
78#define SCRATCH_NETEQ_EXPAND 252
79#else /* NB */
80#define SCRATCH_pw16_expandedLB 210
81#define SCRATCH_pw16_decodedLB 310
82#define SCRATCH_pw32_corr 350
83#define SCRATCH_pw16_corrVec 210
84#define SCRATCH_NETEQ_EXPAND 126
85#endif
86
87int WebRtcNetEQ_Merge(DSPInst_t *inst,
88#ifdef SCRATCH
pbos@webrtc.org0946a562013-04-09 00:28:06 +000089 int16_t *pw16_scratchPtr,
niklase@google.com470e71d2011-07-07 08:21:25 +000090#endif
pbos@webrtc.org0946a562013-04-09 00:28:06 +000091 int16_t *pw16_decoded, int len, int16_t *pw16_outData,
92 int16_t *pw16_len)
niklase@google.com470e71d2011-07-07 08:21:25 +000093{
94
pbos@webrtc.org0946a562013-04-09 00:28:06 +000095 int16_t fs_mult;
96 int16_t fs_shift;
97 int32_t w32_En_new_frame, w32_En_old_frame;
98 int16_t w16_expmax, w16_newmax;
99 int16_t w16_tmp, w16_tmp2;
100 int32_t w32_tmp;
niklase@google.com470e71d2011-07-07 08:21:25 +0000101#ifdef SCRATCH
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000102 int16_t *pw16_expanded = pw16_scratchPtr + SCRATCH_pw16_expanded;
103 int16_t *pw16_expandedLB = pw16_scratchPtr + SCRATCH_pw16_expandedLB;
104 int16_t *pw16_decodedLB = pw16_scratchPtr + SCRATCH_pw16_decodedLB;
105 int32_t *pw32_corr = (int32_t*) (pw16_scratchPtr + SCRATCH_pw32_corr);
106 int16_t *pw16_corrVec = pw16_scratchPtr + SCRATCH_pw16_corrVec;
niklase@google.com470e71d2011-07-07 08:21:25 +0000107#else
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000108 int16_t pw16_expanded[(125+80+5)*FSMULT];
109 int16_t pw16_expandedLB[100];
110 int16_t pw16_decodedLB[40];
111 int32_t pw32_corr[60];
112 int16_t pw16_corrVec[4+60+4];
niklase@google.com470e71d2011-07-07 08:21:25 +0000113#endif
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000114 int16_t *pw16_corr = &pw16_corrVec[4];
115 int16_t w16_stopPos = 0, w16_bestIndex, w16_interpLen;
116 int16_t w16_bestVal; /* bestVal is dummy */
117 int16_t w16_startfact, w16_inc;
118 int16_t w16_expandedLen;
119 int16_t w16_startPos;
120 int16_t w16_expLen, w16_newLen = 0;
121 int16_t *pw16_decodedOut;
122 int16_t w16_muted;
niklase@google.com470e71d2011-07-07 08:21:25 +0000123
124 int w16_decodedLen = len;
125
126#ifdef NETEQ_STEREO
127 MasterSlaveInfo *msInfo = inst->msInfo;
128#endif
129
130 fs_mult = WebRtcSpl_DivW32W16ResW16(inst->fs, 8000);
131 fs_shift = 30 - WebRtcSpl_NormW32(fs_mult); /* Note that this is not "exact" for 48kHz */
132
133 /*************************************
134 * Generate data to merge with
135 *************************************/
136 /*
137 * Check how much data that is left since earlier
138 * (at least there should be the overlap)...
139 */
140 w16_startPos = inst->endPosition - inst->curPosition;
141 /* Get one extra expansion to merge and overlap with */
142 inst->ExpandInst.w16_stopMuting = 1;
143 inst->ExpandInst.w16_lagsDirection = 1; /* make sure we get the "optimal" lag */
144 inst->ExpandInst.w16_lagsPosition = -1; /* out of the 3 possible ones */
145 w16_expandedLen = 0; /* Does not fill any function currently */
146
147 if (w16_startPos >= 210 * FSMULT)
148 {
149 /*
150 * The number of samples available in the sync buffer is more than what fits in
151 * pw16_expanded.Keep the first 210*FSMULT samples, but shift them towards the end of
152 * the buffer. This is ok, since all of the buffer will be expand data anyway, so as
153 * long as the beginning is left untouched, we're fine.
154 */
155
156 w16_tmp = w16_startPos - 210 * FSMULT; /* length difference */
157
158 WEBRTC_SPL_MEMMOVE_W16(&inst->speechBuffer[inst->curPosition+w16_tmp] ,
159 &inst->speechBuffer[inst->curPosition], 210*FSMULT);
160
161 inst->curPosition += w16_tmp; /* move start position of sync buffer accordingly */
162 w16_startPos = 210 * FSMULT; /* this is the truncated length */
163 }
164
165 WebRtcNetEQ_Expand(inst,
166#ifdef SCRATCH
167 pw16_scratchPtr + SCRATCH_NETEQ_EXPAND,
168#endif
169 pw16_expanded, /* let Expand write to beginning of pw16_expanded to avoid overflow */
170 &w16_newLen, 0);
171
172 /*
173 * Now shift the data in pw16_expanded to where it belongs.
174 * Truncate all that ends up outside the vector.
175 */
176
177 WEBRTC_SPL_MEMMOVE_W16(&pw16_expanded[w16_startPos], pw16_expanded,
178 WEBRTC_SPL_MIN(w16_newLen,
179 WEBRTC_SPL_MAX(210*FSMULT - w16_startPos, 0) ) );
180
181 inst->ExpandInst.w16_stopMuting = 0;
182
183 /* Copy what is left since earlier into the expanded vector */
184
185 WEBRTC_SPL_MEMCPY_W16(pw16_expanded, &inst->speechBuffer[inst->curPosition], w16_startPos);
186
187 /*
188 * Do "ugly" copy and paste from the expanded in order to generate more data
189 * to correlate (but not interpolate) with.
190 */
191 w16_expandedLen = (120 + 80 + 2) * fs_mult;
192 w16_expLen = w16_startPos + w16_newLen;
193
194 if (w16_expLen < w16_expandedLen)
195 {
196 while ((w16_expLen + w16_newLen) < w16_expandedLen)
197 {
198 WEBRTC_SPL_MEMCPY_W16(&pw16_expanded[w16_expLen], &pw16_expanded[w16_startPos],
199 w16_newLen);
200 w16_expLen += w16_newLen;
201 }
202
203 /* Copy last part (fraction of a whole expansion) */
204
205 WEBRTC_SPL_MEMCPY_W16(&pw16_expanded[w16_expLen], &pw16_expanded[w16_startPos],
206 (w16_expandedLen-w16_expLen));
207 }
208 w16_expLen = w16_expandedLen;
209
210 /* Adjust muting factor (main muting factor times expand muting factor) */
211 inst->w16_muteFactor
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000212 = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(inst->w16_muteFactor,
niklase@google.com470e71d2011-07-07 08:21:25 +0000213 inst->ExpandInst.w16_expandMuteFactor, 14);
214
215 /* Adjust muting factor if new vector is more or less of the BGN energy */
216 len = WEBRTC_SPL_MIN(64*fs_mult, w16_decodedLen);
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000217 w16_expmax = WebRtcSpl_MaxAbsValueW16(pw16_expanded, (int16_t) len);
218 w16_newmax = WebRtcSpl_MaxAbsValueW16(pw16_decoded, (int16_t) len);
niklase@google.com470e71d2011-07-07 08:21:25 +0000219
220 /* Calculate energy of old data */
221 w16_tmp = 6 + fs_shift - WebRtcSpl_NormW32(WEBRTC_SPL_MUL_16_16(w16_expmax, w16_expmax));
222 w16_tmp = WEBRTC_SPL_MAX(w16_tmp,0);
223 w32_En_old_frame = WebRtcNetEQ_DotW16W16(pw16_expanded, pw16_expanded, len, w16_tmp);
224
225 /* Calculate energy of new data */
226 w16_tmp2 = 6 + fs_shift - WebRtcSpl_NormW32(WEBRTC_SPL_MUL_16_16(w16_newmax, w16_newmax));
227 w16_tmp2 = WEBRTC_SPL_MAX(w16_tmp2,0);
228 w32_En_new_frame = WebRtcNetEQ_DotW16W16(pw16_decoded, pw16_decoded, len, w16_tmp2);
229
230 /* Align to same Q-domain */
231 if (w16_tmp2 > w16_tmp)
232 {
233 w32_En_old_frame = WEBRTC_SPL_RSHIFT_W32(w32_En_old_frame, (w16_tmp2-w16_tmp));
234 }
235 else
236 {
237 w32_En_new_frame = WEBRTC_SPL_RSHIFT_W32(w32_En_new_frame, (w16_tmp-w16_tmp2));
238 }
239
240 /* Calculate muting factor to use for new frame */
241 if (w32_En_new_frame > w32_En_old_frame)
242 {
243 /* Normalize w32_En_new_frame to 14 bits */
244 w16_tmp = WebRtcSpl_NormW32(w32_En_new_frame) - 17;
245 w32_En_new_frame = WEBRTC_SPL_SHIFT_W32(w32_En_new_frame, w16_tmp);
246
247 /*
248 * Put w32_En_old_frame in a domain 14 higher, so that
249 * w32_En_old_frame/w32_En_new_frame is in Q14
250 */
251 w16_tmp = w16_tmp + 14;
252 w32_En_old_frame = WEBRTC_SPL_SHIFT_W32(w32_En_old_frame, w16_tmp);
253 w16_tmp
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000254 = WebRtcSpl_DivW32W16ResW16(w32_En_old_frame, (int16_t) w32_En_new_frame);
niklase@google.com470e71d2011-07-07 08:21:25 +0000255 /* Calculate sqrt(w32_En_old_frame/w32_En_new_frame) in Q14 */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000256 w16_muted = (int16_t) WebRtcSpl_SqrtFloor(
257 WEBRTC_SPL_LSHIFT_W32((int32_t)w16_tmp,14));
niklase@google.com470e71d2011-07-07 08:21:25 +0000258 }
259 else
260 {
261 w16_muted = 16384; /* Set = 1.0 when old frame has higher energy than new */
262 }
263
264 /* Set the raise the continued muting factor w16_muted if w16_muteFactor is lower */
265 if (w16_muted > inst->w16_muteFactor)
266 {
267 inst->w16_muteFactor = WEBRTC_SPL_MIN(w16_muted, 16384);
268 }
269
270#ifdef NETEQ_STEREO
271
272 /* Sanity for msInfo */
273 if (msInfo == NULL)
274 {
275 /* this should not happen here */
276 return MASTER_SLAVE_ERROR;
277 }
278
279 /* do not downsample and calculate correlations for slave instance(s) */
280 if ((msInfo->msMode == NETEQ_MASTER) || (msInfo->msMode == NETEQ_MONO))
281 {
282#endif
283
284 /*********************************************
285 * Downsample to 4kHz and find best overlap
286 *********************************************/
287
288 /* Downsample to 4 kHz */
289 if (inst->fs == 8000)
290 {
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000291 WebRtcSpl_DownsampleFast(&pw16_expanded[2], (int16_t) (w16_expandedLen - 2),
292 pw16_expandedLB, (int16_t) (100),
293 (int16_t*) WebRtcNetEQ_kDownsample8kHzTbl, (int16_t) 3,
294 (int16_t) 2, (int16_t) 0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000295 if (w16_decodedLen <= 80)
296 {
297 /* Not quite long enough, so we have to cheat a bit... */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000298 int16_t temp_len = w16_decodedLen - 2;
henrik.lundin@webrtc.org789da892011-11-25 12:35:31 +0000299 w16_tmp = temp_len / 2;
300 WebRtcSpl_DownsampleFast(&pw16_decoded[2], temp_len,
301 pw16_decodedLB, w16_tmp,
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000302 (int16_t*) WebRtcNetEQ_kDownsample8kHzTbl,
303 (int16_t) 3, (int16_t) 2, (int16_t) 0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000304 WebRtcSpl_MemSetW16(&pw16_decodedLB[w16_tmp], 0, (40 - w16_tmp));
305 }
306 else
307 {
308 WebRtcSpl_DownsampleFast(&pw16_decoded[2],
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000309 (int16_t) (w16_decodedLen - 2), pw16_decodedLB,
310 (int16_t) (40), (int16_t*) WebRtcNetEQ_kDownsample8kHzTbl,
311 (int16_t) 3, (int16_t) 2, (int16_t) 0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000312 }
313#ifdef NETEQ_WIDEBAND
314 }
315 else if (inst->fs==16000)
316 {
317 WebRtcSpl_DownsampleFast(
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000318 &pw16_expanded[4], (int16_t)(w16_expandedLen-4),
319 pw16_expandedLB, (int16_t)(100),
320 (int16_t*)WebRtcNetEQ_kDownsample16kHzTbl, (int16_t)5,
321 (int16_t)4, (int16_t)0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000322 if (w16_decodedLen<=160)
323 {
324 /* Not quite long enough, so we have to cheat a bit... */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000325 int16_t temp_len = w16_decodedLen - 4;
henrik.lundin@webrtc.org789da892011-11-25 12:35:31 +0000326 w16_tmp = temp_len / 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000327 WebRtcSpl_DownsampleFast(
henrik.lundin@webrtc.org789da892011-11-25 12:35:31 +0000328 &pw16_decoded[4], temp_len,
329 pw16_decodedLB, w16_tmp,
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000330 (int16_t*)WebRtcNetEQ_kDownsample16kHzTbl, (int16_t)5,
331 (int16_t)4, (int16_t)0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000332 WebRtcSpl_MemSetW16(&pw16_decodedLB[w16_tmp], 0, (40-w16_tmp));
333 }
334 else
335 {
336 WebRtcSpl_DownsampleFast(
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000337 &pw16_decoded[4], (int16_t)(w16_decodedLen-4),
338 pw16_decodedLB, (int16_t)(40),
339 (int16_t*)WebRtcNetEQ_kDownsample16kHzTbl, (int16_t)5,
340 (int16_t)4, (int16_t)0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000341 }
342#endif
343#ifdef NETEQ_32KHZ_WIDEBAND
344 }
345 else if (inst->fs==32000)
346 {
henrik.lundin@webrtc.org789da892011-11-25 12:35:31 +0000347 /*
348 * TODO(hlundin) Why is the offset into pw16_expanded 6?
349 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000350 WebRtcSpl_DownsampleFast(
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000351 &pw16_expanded[6], (int16_t)(w16_expandedLen-6),
352 pw16_expandedLB, (int16_t)(100),
353 (int16_t*)WebRtcNetEQ_kDownsample32kHzTbl, (int16_t)7,
354 (int16_t)8, (int16_t)0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000355 if (w16_decodedLen<=320)
356 {
357 /* Not quite long enough, so we have to cheat a bit... */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000358 int16_t temp_len = w16_decodedLen - 6;
henrik.lundin@webrtc.org789da892011-11-25 12:35:31 +0000359 w16_tmp = temp_len / 8;
niklase@google.com470e71d2011-07-07 08:21:25 +0000360 WebRtcSpl_DownsampleFast(
henrik.lundin@webrtc.org789da892011-11-25 12:35:31 +0000361 &pw16_decoded[6], temp_len,
362 pw16_decodedLB, w16_tmp,
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000363 (int16_t*)WebRtcNetEQ_kDownsample32kHzTbl, (int16_t)7,
364 (int16_t)8, (int16_t)0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000365 WebRtcSpl_MemSetW16(&pw16_decodedLB[w16_tmp], 0, (40-w16_tmp));
366 }
367 else
368 {
369 WebRtcSpl_DownsampleFast(
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000370 &pw16_decoded[6], (int16_t)(w16_decodedLen-6),
371 pw16_decodedLB, (int16_t)(40),
372 (int16_t*)WebRtcNetEQ_kDownsample32kHzTbl, (int16_t)7,
373 (int16_t)8, (int16_t)0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000374 }
375#endif
376#ifdef NETEQ_48KHZ_WIDEBAND
377 }
378 else /* if (inst->fs==48000) */
379 {
henrik.lundin@webrtc.org789da892011-11-25 12:35:31 +0000380 /*
381 * TODO(hlundin) Why is the offset into pw16_expanded 6?
382 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000383 WebRtcSpl_DownsampleFast(
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000384 &pw16_expanded[6], (int16_t)(w16_expandedLen-6),
385 pw16_expandedLB, (int16_t)(100),
386 (int16_t*)WebRtcNetEQ_kDownsample48kHzTbl, (int16_t)7,
387 (int16_t)12, (int16_t)0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000388 if (w16_decodedLen<=320)
389 {
390 /* Not quite long enough, so we have to cheat a bit... */
henrik.lundin@webrtc.org789da892011-11-25 12:35:31 +0000391 /*
392 * TODO(hlundin): Is this correct? Downsampling is a factor 12
393 * but w16_tmp = temp_len / 8.
394 * (Was w16_tmp = ((w16_decodedLen-6)>>3) before re-write.)
395 */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000396 int16_t temp_len = w16_decodedLen - 6;
henrik.lundin@webrtc.org789da892011-11-25 12:35:31 +0000397 w16_tmp = temp_len / 8;
niklase@google.com470e71d2011-07-07 08:21:25 +0000398 WebRtcSpl_DownsampleFast(
henrik.lundin@webrtc.org789da892011-11-25 12:35:31 +0000399 &pw16_decoded[6], temp_len,
400 pw16_decodedLB, w16_tmp,
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000401 (int16_t*)WebRtcNetEQ_kDownsample48kHzTbl, (int16_t)7,
402 (int16_t)12, (int16_t)0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000403 WebRtcSpl_MemSetW16(&pw16_decodedLB[w16_tmp], 0, (40-w16_tmp));
404 }
405 else
406 {
407 WebRtcSpl_DownsampleFast(
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000408 &pw16_decoded[6], (int16_t)(w16_decodedLen-6),
409 pw16_decodedLB, (int16_t)(40),
410 (int16_t*)WebRtcNetEQ_kDownsample48kHzTbl, (int16_t)7,
411 (int16_t)12, (int16_t)0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000412 }
413#endif
414 }
415
416 /* Calculate correlation without any normalization (40 samples) */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000417 w16_tmp = WebRtcSpl_DivW32W16ResW16((int32_t) inst->ExpandInst.w16_maxLag,
418 (int16_t) (fs_mult * 2)) + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000419 w16_stopPos = WEBRTC_SPL_MIN(60, w16_tmp);
420 w32_tmp = WEBRTC_SPL_MUL_16_16(w16_expmax, w16_newmax);
421 if (w32_tmp > 26843546)
422 {
423 w16_tmp = 3;
424 }
425 else
426 {
427 w16_tmp = 0;
428 }
429
430 WebRtcNetEQ_CrossCorr(pw32_corr, pw16_decodedLB, pw16_expandedLB, 40,
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000431 (int16_t) w16_stopPos, w16_tmp, 1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000432
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000433 /* Normalize correlation to 14 bits and put in a int16_t vector */
niklase@google.com470e71d2011-07-07 08:21:25 +0000434 WebRtcSpl_MemSetW16(pw16_corrVec, 0, (4 + 60 + 4));
435 w32_tmp = WebRtcSpl_MaxAbsValueW32(pw32_corr, w16_stopPos);
436 w16_tmp = 17 - WebRtcSpl_NormW32(w32_tmp);
437 w16_tmp = WEBRTC_SPL_MAX(0, w16_tmp);
438
439 WebRtcSpl_VectorBitShiftW32ToW16(pw16_corr, w16_stopPos, pw32_corr, w16_tmp);
440
441 /* Calculate allowed starting point for peak finding.
442 The peak location bestIndex must fulfill two criteria:
443 (1) w16_bestIndex+w16_decodedLen < inst->timestampsPerCall+inst->ExpandInst.w16_overlap
444 (2) w16_bestIndex+w16_decodedLen < w16_startPos */
445 w16_tmp = WEBRTC_SPL_MAX(0, WEBRTC_SPL_MAX(w16_startPos,
446 inst->timestampsPerCall+inst->ExpandInst.w16_overlap) - w16_decodedLen);
447 /* Downscale starting index to 4kHz domain */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000448 w16_tmp2 = WebRtcSpl_DivW32W16ResW16((int32_t) w16_tmp,
449 (int16_t) (fs_mult << 1));
niklase@google.com470e71d2011-07-07 08:21:25 +0000450
451#ifdef NETEQ_STEREO
452 } /* end if (msInfo->msMode != NETEQ_SLAVE) */
453
454 if ((msInfo->msMode == NETEQ_MASTER) || (msInfo->msMode == NETEQ_MONO))
455 {
456 /* This is master or mono instance; find peak */
457 WebRtcNetEQ_PeakDetection(&pw16_corr[w16_tmp2], w16_stopPos, 1, fs_mult, &w16_bestIndex,
458 &w16_bestVal);
459 w16_bestIndex += w16_tmp; /* compensate for modified starting index */
460 msInfo->bestIndex = w16_bestIndex;
461 }
462 else if (msInfo->msMode == NETEQ_SLAVE)
463 {
464 /* Get peak location from master instance */
465 w16_bestIndex = msInfo->bestIndex;
466 }
467 else
468 {
469 /* Invalid mode */
470 return MASTER_SLAVE_ERROR;
471 }
472
473#else /* NETEQ_STEREO */
474
475 /* Find peak */
476 WebRtcNetEQ_PeakDetection(&pw16_corr[w16_tmp2], w16_stopPos, 1, fs_mult, &w16_bestIndex,
477 &w16_bestVal);
478 w16_bestIndex += w16_tmp; /* compensate for modified starting index */
479
480#endif /* NETEQ_STEREO */
481
482 /*
483 * Ensure that underrun does not occur for 10ms case => we have to get at least
484 * 10ms + overlap . (This should never happen thanks to the above modification of
485 * peak-finding starting point.)
486 * */
487 while ((w16_bestIndex + w16_decodedLen) < (inst->timestampsPerCall
488 + inst->ExpandInst.w16_overlap) || w16_bestIndex + w16_decodedLen < w16_startPos)
489 {
490 w16_bestIndex += w16_newLen; /* Jump one lag ahead */
491 }
492 pw16_decodedOut = pw16_outData + w16_bestIndex;
493
494 /* Mute the new decoded data if needed (and unmute it linearly) */
495 w16_interpLen = WEBRTC_SPL_MIN(60*fs_mult,
496 w16_expandedLen-w16_bestIndex); /* this is the overlapping part of pw16_expanded */
497 w16_interpLen = WEBRTC_SPL_MIN(w16_interpLen, w16_decodedLen);
498 w16_inc = WebRtcSpl_DivW32W16ResW16(4194,
499 fs_mult); /* in Q20, 0.004 for NB and 0.002 for WB */
500 if (inst->w16_muteFactor < 16384)
501 {
502 WebRtcNetEQ_UnmuteSignal(pw16_decoded, &inst->w16_muteFactor, pw16_decoded, w16_inc,
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000503 (int16_t) w16_interpLen);
niklase@google.com470e71d2011-07-07 08:21:25 +0000504 WebRtcNetEQ_UnmuteSignal(&pw16_decoded[w16_interpLen], &inst->w16_muteFactor,
505 &pw16_decodedOut[w16_interpLen], w16_inc,
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000506 (int16_t) (w16_decodedLen - w16_interpLen));
niklase@google.com470e71d2011-07-07 08:21:25 +0000507 }
508 else
509 {
510 /* No muting needed */
511
512 WEBRTC_SPL_MEMMOVE_W16(&pw16_decodedOut[w16_interpLen], &pw16_decoded[w16_interpLen],
513 (w16_decodedLen-w16_interpLen));
514 }
515
516 /* Do overlap and interpolate linearly */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000517 w16_inc = WebRtcSpl_DivW32W16ResW16(16384, (int16_t) (w16_interpLen + 1)); /* Q14 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000518 w16_startfact = (16384 - w16_inc);
519 WEBRTC_SPL_MEMMOVE_W16(pw16_outData, pw16_expanded, w16_bestIndex);
520 WebRtcNetEQ_MixVoiceUnvoice(pw16_decodedOut, &pw16_expanded[w16_bestIndex], pw16_decoded,
521 &w16_startfact, w16_inc, w16_interpLen);
522
523 inst->w16_mode = MODE_MERGE;
524 inst->ExpandInst.w16_consecExp = 0; /* Last was not expand any more */
525
526 /* New added length (w16_startPos samples were borrowed) */
527 *pw16_len = w16_bestIndex + w16_decodedLen - w16_startPos;
528
529 /* Update VQmon parameter */
530 inst->w16_concealedTS += (*pw16_len - w16_decodedLen);
531 inst->w16_concealedTS = WEBRTC_SPL_MAX(0, inst->w16_concealedTS);
532
533 /* Update in-call and post-call statistics */
534 if (inst->ExpandInst.w16_expandMuteFactor == 0)
535 {
536 /* expansion generates noise only */
537 inst->statInst.expandedNoiseSamples += (*pw16_len - w16_decodedLen);
turaj@webrtc.org92d1f072013-04-15 16:52:04 +0000538 /* Short-term activity statistics. */
539 inst->activity_stats.merge_expand_bgn_samples +=
540 (*pw16_len - w16_decodedLen);
niklase@google.com470e71d2011-07-07 08:21:25 +0000541 }
542 else
543 {
544 /* expansion generates more than only noise */
545 inst->statInst.expandedVoiceSamples += (*pw16_len - w16_decodedLen);
turaj@webrtc.org92d1f072013-04-15 16:52:04 +0000546 /* Short-term activity statistics. */
547 inst->activity_stats.merge_expand_normal_samples +=
548 (*pw16_len - w16_decodedLen);
niklase@google.com470e71d2011-07-07 08:21:25 +0000549 }
550 inst->statInst.expandLength += (*pw16_len - w16_decodedLen);
551
552
553 /* Copy back the first part of the data to the speechHistory */
554
555 WEBRTC_SPL_MEMCPY_W16(&inst->speechBuffer[inst->curPosition], pw16_outData, w16_startPos);
556
557
558 /* Move data to within outData */
559
560 WEBRTC_SPL_MEMMOVE_W16(pw16_outData, &pw16_outData[w16_startPos], (*pw16_len));
561
562 return 0;
563}
564
565#undef SCRATCH_pw16_expanded
566#undef SCRATCH_pw16_expandedLB
567#undef SCRATCH_pw16_decodedLB
568#undef SCRATCH_pw32_corr
569#undef SCRATCH_pw16_corrVec
570#undef SCRATCH_NETEQ_EXPAND