blob: 9959f9222d7ca5642df90042e88aa971e8181da5 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3 *
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 expand from the speech history, to produce concealment data or
13 * increasing delay.
14 */
15
16#include "dsp.h"
17
henrik.lundin@webrtc.org598ad062011-12-07 11:52:09 +000018#include <assert.h>
19
niklase@google.com470e71d2011-07-07 08:21:25 +000020#include "signal_processing_library.h"
21
22#include "dsp_helpfunctions.h"
23#include "neteq_error_codes.h"
24
25#define CHECK_NO_OF_CORRMAX 3
26#define DISTLEN 20
27#define LPCANALASYSLEN 160
28
29/* Scratch usage:
30
31 Type Name size startpos endpos
32 (First part of first expand)
pbos@webrtc.org0946a562013-04-09 00:28:06 +000033 int16_t pw16_bestCorrIndex 3 0 2
34 int16_t pw16_bestCorr 3 3 5
35 int16_t pw16_bestDistIndex 3 6 8
36 int16_t pw16_bestDist 3 9 11
37 int16_t pw16_corrVec 102*fs/8000 12 11+102*fs/8000
niklase@google.com470e71d2011-07-07 08:21:25 +000038 func WebRtcNetEQ_Correlator 232 12+102*fs/8000 243+102*fs/8000
39
40 (Second part of first expand)
pbos@webrtc.org0946a562013-04-09 00:28:06 +000041 int32_t pw32_corr2 99*fs/8000+1 0 99*fs/8000
42 int32_t pw32_autoCorr 2*7 0 13
43 int16_t pw16_rc 6 14 19
niklase@google.com470e71d2011-07-07 08:21:25 +000044
45 Signal combination:
pbos@webrtc.org0946a562013-04-09 00:28:06 +000046 int16_t pw16_randVec 30+120*fs/8000 0 29+120*fs/8000
47 int16_t pw16_scaledRandVec 125*fs/8000 30+120*fs/8000 29+245*fs/8000
48 int16_t pw16_unvoicedVecSpace 10+125*fs/8000 30+245*fs/8000 39+370*fs/8000
niklase@google.com470e71d2011-07-07 08:21:25 +000049
50 Total: 40+370*fs/8000 (size depends on UNVOICED_LPC_ORDER and BGN_LPC_ORDER)
51 */
52
53#if ((BGN_LPC_ORDER > 10) || (UNVOICED_LPC_ORDER > 10)) && (defined SCRATCH)
54#error BGN_LPC_ORDER and/or BGN_LPC_ORDER are too large for current scratch memory allocation
55#endif
56
57#define SCRATCH_PW16_BEST_CORR_INDEX 0
58#define SCRATCH_PW16_BEST_CORR 3
59#define SCRATCH_PW16_BEST_DIST_INDEX 6
60#define SCRATCH_PW16_BEST_DIST 9
61#define SCRATCH_PW16_CORR_VEC 12
62#define SCRATCH_PW16_CORR2 0
63#define SCRATCH_PW32_AUTO_CORR 0
64#define SCRATCH_PW16_RC 14
65#define SCRATCH_PW16_RAND_VEC 0
66
67#if (defined(NETEQ_48KHZ_WIDEBAND))
68#define SCRATCH_NETEQDSP_CORRELATOR 624
69#define SCRATCH_PW16_SCALED_RAND_VEC 750
70#define SCRATCH_PW16_UNVOICED_VEC_SPACE 1500
71#elif (defined(NETEQ_32KHZ_WIDEBAND))
72#define SCRATCH_NETEQDSP_CORRELATOR 420
73#define SCRATCH_PW16_SCALED_RAND_VEC 510
74#define SCRATCH_PW16_UNVOICED_VEC_SPACE 1010
75#elif (defined(NETEQ_WIDEBAND))
76#define SCRATCH_NETEQDSP_CORRELATOR 216
77#define SCRATCH_PW16_SCALED_RAND_VEC 270
78#define SCRATCH_PW16_UNVOICED_VEC_SPACE 520
79#else /* NB */
80#define SCRATCH_NETEQDSP_CORRELATOR 114
81#define SCRATCH_PW16_SCALED_RAND_VEC 150
82#define SCRATCH_PW16_UNVOICED_VEC_SPACE 275
83#endif
84
85/****************************************************************************
86 * WebRtcNetEQ_Expand(...)
87 *
88 * This function produces one "chunk" of expansion data (PLC audio). The
89 * length of the produced audio depends on the speech history.
90 *
91 * Input:
92 * - inst : DSP instance
93 * - scratchPtr : Pointer to scratch vector
94 * - outdata : Pointer to a memory space where the output data
95 * should be stored
96 * - BGNonly : If non-zero, "expand" will only produce background noise.
97 * - pw16_len : Desired number of samples (only for BGN mode).
98 *
99 * Output:
100 * - inst : Updated instance
101 * - pw16_len : Number of samples that were output from NetEq
102 *
103 * Return value : 0 - Ok
104 * <0 - Error
105 */
106
107int WebRtcNetEQ_Expand(DSPInst_t *inst,
108#ifdef SCRATCH
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000109 int16_t *pw16_scratchPtr,
niklase@google.com470e71d2011-07-07 08:21:25 +0000110#endif
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000111 int16_t *pw16_outData, int16_t *pw16_len,
112 int16_t BGNonly)
niklase@google.com470e71d2011-07-07 08:21:25 +0000113{
114
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000115 int16_t fs_mult;
niklase@google.com470e71d2011-07-07 08:21:25 +0000116 ExpandInst_t *ExpandState = &(inst->ExpandInst);
117 BGNInst_t *BGNState = &(inst->BGNInst);
118 int i;
119#ifdef SCRATCH
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000120 int16_t *pw16_randVec = pw16_scratchPtr + SCRATCH_PW16_RAND_VEC;
121 int16_t *pw16_scaledRandVec = pw16_scratchPtr + SCRATCH_PW16_SCALED_RAND_VEC;
122 int16_t *pw16_unvoicedVecSpace = pw16_scratchPtr + SCRATCH_PW16_UNVOICED_VEC_SPACE;
niklase@google.com470e71d2011-07-07 08:21:25 +0000123#else
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000124 int16_t pw16_randVec[FSMULT * 120 + 30]; /* 150 for NB and 270 for WB */
125 int16_t pw16_scaledRandVec[FSMULT * 125]; /* 125 for NB and 250 for WB */
126 int16_t pw16_unvoicedVecSpace[BGN_LPC_ORDER + FSMULT * 125];
niklase@google.com470e71d2011-07-07 08:21:25 +0000127#endif
128 /* 125 for NB and 250 for WB etc. Reuse pw16_outData[] for this vector */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000129 int16_t *pw16_voicedVecStorage = pw16_outData;
130 int16_t *pw16_voicedVec = &pw16_voicedVecStorage[ExpandState->w16_overlap];
131 int16_t *pw16_unvoicedVec = pw16_unvoicedVecSpace + UNVOICED_LPC_ORDER;
132 int16_t *pw16_cngVec = pw16_unvoicedVecSpace + BGN_LPC_ORDER;
133 int16_t w16_expVecsLen, w16_lag = 0, w16_expVecPos;
134 int16_t w16_randLen;
135 int16_t w16_vfractionChange; /* in Q14 */
136 int16_t w16_winMute = 0, w16_winMuteInc = 0, w16_winUnMute = 0, w16_winUnMuteInc = 0;
137 int32_t w32_tmp;
138 int16_t w16_tmp, w16_tmp2;
139 int16_t stability;
niklase@google.com470e71d2011-07-07 08:21:25 +0000140 enum BGNMode bgnMode = inst->BGNInst.bgnMode;
141
142 /* Pre-calculate common multiplications with fs_mult */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000143 int16_t fsMult4;
144 int16_t fsMult20;
145 int16_t fsMult120;
146 int16_t fsMultDistLen;
147 int16_t fsMultLPCAnalasysLen;
niklase@google.com470e71d2011-07-07 08:21:25 +0000148
149#ifdef NETEQ_STEREO
150 MasterSlaveInfo *msInfo = inst->msInfo;
151#endif
152
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000153 /* fs is uint16_t (to hold fs=48000) */
niklase@google.com470e71d2011-07-07 08:21:25 +0000154 fs_mult = WebRtcNetEQ_CalcFsMult(inst->fs); /* calculate fs/8000 */
155
156 /* Pre-calculate common multiplications with fs_mult */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000157 fsMult4 = (int16_t) WEBRTC_SPL_MUL_16_16(fs_mult, 4);
158 fsMult20 = (int16_t) WEBRTC_SPL_MUL_16_16(fs_mult, 20);
159 fsMult120 = (int16_t) WEBRTC_SPL_MUL_16_16(fs_mult, 120);
160 fsMultDistLen = (int16_t) WEBRTC_SPL_MUL_16_16(fs_mult, DISTLEN);
161 fsMultLPCAnalasysLen = (int16_t) WEBRTC_SPL_MUL_16_16(fs_mult, LPCANALASYSLEN);
niklase@google.com470e71d2011-07-07 08:21:25 +0000162
163 /*
164 * Perform all the initial setup if it's the first expansion.
165 * If background noise (BGN) only, this setup is not needed.
166 */
167 if (ExpandState->w16_consecExp == 0 && !BGNonly)
168 {
169 /* Setup more variables */
170#ifdef SCRATCH
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000171 int32_t *pw32_autoCorr = (int32_t*) (pw16_scratchPtr
niklase@google.com470e71d2011-07-07 08:21:25 +0000172 + SCRATCH_PW32_AUTO_CORR);
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000173 int16_t *pw16_rc = pw16_scratchPtr + SCRATCH_PW16_RC;
174 int16_t *pw16_bestCorrIndex = pw16_scratchPtr + SCRATCH_PW16_BEST_CORR_INDEX;
175 int16_t *pw16_bestCorr = pw16_scratchPtr + SCRATCH_PW16_BEST_CORR;
176 int16_t *pw16_bestDistIndex = pw16_scratchPtr + SCRATCH_PW16_BEST_DIST_INDEX;
177 int16_t *pw16_bestDist = pw16_scratchPtr + SCRATCH_PW16_BEST_DIST;
178 int16_t *pw16_corrVec = pw16_scratchPtr + SCRATCH_PW16_CORR_VEC;
179 int32_t *pw32_corr2 = (int32_t*) (pw16_scratchPtr + SCRATCH_PW16_CORR2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000180#else
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000181 int32_t pw32_autoCorr[UNVOICED_LPC_ORDER+1];
182 int16_t pw16_rc[UNVOICED_LPC_ORDER];
183 int16_t pw16_corrVec[FSMULT*102]; /* 102 for NB */
184 int16_t pw16_bestCorrIndex[CHECK_NO_OF_CORRMAX];
185 int16_t pw16_bestCorr[CHECK_NO_OF_CORRMAX];
186 int16_t pw16_bestDistIndex[CHECK_NO_OF_CORRMAX];
187 int16_t pw16_bestDist[CHECK_NO_OF_CORRMAX];
188 int32_t pw32_corr2[(99*FSMULT)+1];
niklase@google.com470e71d2011-07-07 08:21:25 +0000189#endif
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000190 int32_t pw32_bestDist[CHECK_NO_OF_CORRMAX];
191 int16_t w16_ind = 0;
192 int16_t w16_corrVecLen;
193 int16_t w16_corrScale;
194 int16_t w16_distScale;
195 int16_t w16_indMin, w16_indMax;
196 int16_t w16_len;
197 int32_t w32_en1, w32_en2, w32_cc;
198 int16_t w16_en1Scale, w16_en2Scale;
199 int16_t w16_en1, w16_en2;
200 int32_t w32_en1_mul_en2;
201 int16_t w16_sqrt_en1en2;
202 int16_t w16_ccShiftL;
203 int16_t w16_bestcorr; /* Correlation in Q14 */
204 int16_t *pw16_vec1, *pw16_vec2;
205 int16_t w16_factor;
206 int16_t w16_DistLag, w16_CorrLag, w16_diffLag;
207 int16_t w16_energyLen;
208 int16_t w16_slope;
209 int16_t w16_startInd;
210 int16_t w16_noOfcorr2;
211 int16_t w16_scale;
niklase@google.com470e71d2011-07-07 08:21:25 +0000212
213 /* Initialize some variables */
214 ExpandState->w16_lagsDirection = 1;
215 ExpandState->w16_lagsPosition = -1;
216 ExpandState->w16_expandMuteFactor = 16384; /* Start from 1.0 (Q14) */
217 BGNState->w16_mutefactor = 0; /* Start with 0 gain for BGN (value in Q14) */
218 inst->w16_seedInc = 1;
219
220#ifdef NETEQ_STEREO
221 /* Sanity for msInfo */
222 if (msInfo == NULL)
223 {
224 /* this should not happen here */
225 return MASTER_SLAVE_ERROR;
226 }
227
228 /*
229 * Do not calculate correlations for slave instance(s)
230 * unless lag info from master is corrupt
231 */
232 if ((msInfo->msMode != NETEQ_SLAVE)
233 || ((msInfo->distLag <= 0) || (msInfo->corrLag <= 0)))
234 {
235#endif
236 /* Calculate correlation vector in downsampled domain (4 kHz sample rate) */
237 w16_corrVecLen = WebRtcNetEQ_Correlator(inst,
238#ifdef SCRATCH
239 pw16_scratchPtr + SCRATCH_NETEQDSP_CORRELATOR,
240#endif
241 inst->pw16_speechHistory, inst->w16_speechHistoryLen, pw16_corrVec,
242 &w16_corrScale);
243
244 /* Find peaks in correlation vector using parabolic fit method */
245 WebRtcNetEQ_PeakDetection(pw16_corrVec, w16_corrVecLen, CHECK_NO_OF_CORRMAX, fs_mult,
246 pw16_bestCorrIndex, pw16_bestCorr);
247
248 /*
249 * Adjust peak locations; cross-correlation lags start at 2.5 ms
250 * (20*fs_mult samples)
251 */
252 pw16_bestCorrIndex[0] += fsMult20;
253 pw16_bestCorrIndex[1] += fsMult20;
254 pw16_bestCorrIndex[2] += fsMult20;
255
256 /* Calculate distortion around the 3 (CHECK_NO_OF_CORRMAX) best lags */
257 w16_distScale = 0;
258 for (i = 0; i < CHECK_NO_OF_CORRMAX; i++)
259 {
260 w16_tmp = fsMult20;
261 w16_tmp2 = pw16_bestCorrIndex[i] - fsMult4;
262 w16_indMin = WEBRTC_SPL_MAX(w16_tmp, w16_tmp2);
263 w16_tmp = fsMult120 - 1;
264 w16_tmp2 = pw16_bestCorrIndex[i] + fsMult4;
265 w16_indMax = WEBRTC_SPL_MIN(w16_tmp, w16_tmp2);
266
267 pw16_bestDistIndex[i] = WebRtcNetEQ_MinDistortion(
268 &(inst->pw16_speechHistory[inst->w16_speechHistoryLen - fsMultDistLen]),
269 w16_indMin, w16_indMax, fsMultDistLen, &pw32_bestDist[i]);
270
271 w16_distScale
272 = WEBRTC_SPL_MAX(16 - WebRtcSpl_NormW32(pw32_bestDist[i]), w16_distScale);
273
274 }
275
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000276 /* Shift the distortion values to fit in int16_t */
niklase@google.com470e71d2011-07-07 08:21:25 +0000277 WebRtcSpl_VectorBitShiftW32ToW16(pw16_bestDist, CHECK_NO_OF_CORRMAX, pw32_bestDist,
278 w16_distScale);
279
280 /*
281 * Find index of maximum criteria, where crit[i] = bestCorr[i])/(bestDist[i])
282 * Do this by a cross multiplication.
283 */
284
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000285 w32_en1 = WEBRTC_SPL_MUL_16_16((int32_t) pw16_bestCorr[0],pw16_bestDist[1]);
286 w32_en2 = WEBRTC_SPL_MUL_16_16((int32_t) pw16_bestCorr[1],pw16_bestDist[0]);
niklase@google.com470e71d2011-07-07 08:21:25 +0000287 if (w32_en1 >= w32_en2)
288 {
289 /* 0 wins over 1 */
290 w32_en1
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000291 = WEBRTC_SPL_MUL_16_16((int32_t) pw16_bestCorr[0], pw16_bestDist[2]);
niklase@google.com470e71d2011-07-07 08:21:25 +0000292 w32_en2
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000293 = WEBRTC_SPL_MUL_16_16((int32_t) pw16_bestCorr[2], pw16_bestDist[0]);
niklase@google.com470e71d2011-07-07 08:21:25 +0000294 if (w32_en1 >= w32_en2)
295 {
296 /* 0 wins over 2 */
297 w16_ind = 0;
298 }
299 else
300 {
301 /* 2 wins over 0 */
302 w16_ind = 2;
303 }
304 }
305 else
306 {
307 /* 1 wins over 0 */
308 w32_en1
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000309 = WEBRTC_SPL_MUL_16_16((int32_t) pw16_bestCorr[1],pw16_bestDist[2]);
niklase@google.com470e71d2011-07-07 08:21:25 +0000310 w32_en2
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000311 = WEBRTC_SPL_MUL_16_16((int32_t) pw16_bestCorr[2],pw16_bestDist[1]);
312 if ((int32_t) w32_en1 >= (int32_t) w32_en2)
niklase@google.com470e71d2011-07-07 08:21:25 +0000313 {
314 /* 1 wins over 2 */
315 w16_ind = 1;
316 }
317 else
318 {
319 /* 2 wins over 1 */
320 w16_ind = 2;
321 }
322 }
323
324#ifdef NETEQ_STEREO
325 }
326
327 /* Store DistLag and CorrLag of the position with highest criteria */
328 if ((msInfo->msMode == NETEQ_MASTER) || (msInfo->msMode == NETEQ_MONO)
329 || ((msInfo->msMode == NETEQ_SLAVE) && (msInfo->distLag <= 0 || msInfo->corrLag
330 <= 0)))
331 {
332 /* lags not provided externally */
333 w16_DistLag = pw16_bestDistIndex[w16_ind];
334 w16_CorrLag = pw16_bestCorrIndex[w16_ind];
335 if (msInfo->msMode == NETEQ_MASTER)
336 {
337 msInfo->distLag = w16_DistLag;
338 msInfo->corrLag = w16_CorrLag;
339 }
340 }
341 else if (msInfo->msMode == NETEQ_SLAVE)
342 {
343 /* lags provided externally (from master) */
344 w16_DistLag = msInfo->distLag;
345 w16_CorrLag = msInfo->corrLag;
346
347 /* sanity for lag values */
348 if ((w16_DistLag <= 0) || (w16_CorrLag <= 0))
349 {
350 return MASTER_SLAVE_ERROR;
351 }
352 }
353 else
354 {
355 /* Invalid mode */
356 return MASTER_SLAVE_ERROR;
357 }
358#else /* not NETEQ_STEREO */
359 w16_DistLag = pw16_bestDistIndex[w16_ind];
360 w16_CorrLag = pw16_bestCorrIndex[w16_ind];
361#endif
362
363 ExpandState->w16_maxLag = WEBRTC_SPL_MAX(w16_DistLag, w16_CorrLag);
364
365 /* Calculate the exact best correlation (in the range within CorrLag-DistLag) */
366 w16_len = w16_DistLag + 10;
367 w16_len = WEBRTC_SPL_MIN(w16_len, fsMult120);
368 w16_len = WEBRTC_SPL_MAX(w16_len, 60 * fs_mult);
369
370 w16_startInd = WEBRTC_SPL_MIN(w16_DistLag, w16_CorrLag);
371 w16_noOfcorr2 = WEBRTC_SPL_ABS_W16((w16_DistLag-w16_CorrLag)) + 1;
372 /* w16_noOfcorr2 maximum value is 99*fs_mult + 1 */
373
374 /* Calculate suitable scaling */
375 w16_tmp
376 = WebRtcSpl_MaxAbsValueW16(
377 &inst->pw16_speechHistory[inst->w16_speechHistoryLen - w16_len - w16_startInd
378 - w16_noOfcorr2],
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000379 (int16_t) (w16_len + w16_startInd + w16_noOfcorr2 - 1));
niklase@google.com470e71d2011-07-07 08:21:25 +0000380 w16_corrScale = ((31 - WebRtcSpl_NormW32(WEBRTC_SPL_MUL_16_16(w16_tmp, w16_tmp)))
381 + (31 - WebRtcSpl_NormW32(w16_len))) - 31;
382 w16_corrScale = WEBRTC_SPL_MAX(0, w16_corrScale);
383
384 /*
385 * Perform the correlation, store in pw32_corr2
386 */
387
388 WebRtcNetEQ_CrossCorr(pw32_corr2,
389 &(inst->pw16_speechHistory[inst->w16_speechHistoryLen - w16_len]),
390 &(inst->pw16_speechHistory[inst->w16_speechHistoryLen - w16_len - w16_startInd]),
391 w16_len, w16_noOfcorr2, w16_corrScale, -1);
392
393 /* Find maximizing index */
394 w16_ind = WebRtcSpl_MaxIndexW32(pw32_corr2, w16_noOfcorr2);
395 w32_cc = pw32_corr2[w16_ind]; /* this is maximum correlation */
396 w16_ind = w16_ind + w16_startInd; /* correct index for start offset */
397
398 /* Calculate energies */
399 w32_en1 = WebRtcNetEQ_DotW16W16(
400 &(inst->pw16_speechHistory[inst->w16_speechHistoryLen - w16_len]),
401 &(inst->pw16_speechHistory[inst->w16_speechHistoryLen - w16_len]), w16_len,
402 w16_corrScale);
403 w32_en2 = WebRtcNetEQ_DotW16W16(
404 &(inst->pw16_speechHistory[inst->w16_speechHistoryLen - w16_len - w16_ind]),
405 &(inst->pw16_speechHistory[inst->w16_speechHistoryLen - w16_len - w16_ind]),
406 w16_len, w16_corrScale);
407
408 /* Calculate the correlation value w16_bestcorr */
409 if ((w32_en1 > 0) && (w32_en2 > 0))
410 {
411 w16_en1Scale = 16 - WebRtcSpl_NormW32(w32_en1);
412 w16_en1Scale = WEBRTC_SPL_MAX(0, w16_en1Scale);
413 w16_en2Scale = 16 - WebRtcSpl_NormW32(w32_en2);
414 w16_en2Scale = WEBRTC_SPL_MAX(0, w16_en2Scale);
415 /* Make sure total scaling is even (to simplify scale factor after sqrt) */
416 if ((w16_en1Scale + w16_en2Scale) & 1)
417 {
418 /* if sum is odd */
419 w16_en1Scale += 1;
420 }
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000421 w16_en1 = (int16_t) WEBRTC_SPL_RSHIFT_W32(w32_en1, w16_en1Scale);
422 w16_en2 = (int16_t) WEBRTC_SPL_RSHIFT_W32(w32_en2, w16_en2Scale);
niklase@google.com470e71d2011-07-07 08:21:25 +0000423 w32_en1_mul_en2 = WEBRTC_SPL_MUL_16_16(w16_en1, w16_en2);
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000424 w16_sqrt_en1en2 = (int16_t) WebRtcSpl_SqrtFloor(w32_en1_mul_en2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000425
426 /* Calculate cc/sqrt(en1*en2) in Q14 */
427 w16_ccShiftL = 14 - ((w16_en1Scale + w16_en2Scale) >> 1);
428 w32_cc = WEBRTC_SPL_SHIFT_W32(w32_cc, w16_ccShiftL);
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000429 w16_bestcorr = (int16_t) WebRtcSpl_DivW32W16(w32_cc, w16_sqrt_en1en2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000430 w16_bestcorr = WEBRTC_SPL_MIN(16384, w16_bestcorr); /* set maximum to 1.0 */
431
432 }
433 else
434 {
435 /* if either en1 or en2 is zero */
436 w16_bestcorr = 0;
437 }
438
439 /*
440 * Extract the two vectors, pw16_expVecs[0][] and pw16_expVecs[1][],
441 * from the SpeechHistory[]
442 */
443 w16_expVecsLen = ExpandState->w16_maxLag + ExpandState->w16_overlap;
444 pw16_vec1 = &(inst->pw16_speechHistory[inst->w16_speechHistoryLen - w16_expVecsLen]);
445 pw16_vec2 = pw16_vec1 - w16_DistLag;
446 /* Normalize the second vector to the same energy as the first */
447 w32_en1 = WebRtcNetEQ_DotW16W16(pw16_vec1, pw16_vec1, w16_expVecsLen, w16_corrScale);
448 w32_en2 = WebRtcNetEQ_DotW16W16(pw16_vec2, pw16_vec2, w16_expVecsLen, w16_corrScale);
449
450 /*
451 * Confirm that energy factor sqrt(w32_en1/w32_en2) is within difference 0.5 - 2.0
452 * w32_en1/w32_en2 within 0.25 - 4
453 */
454 if (((w32_en1 >> 2) < w32_en2) && ((w32_en1) > (w32_en2 >> 2)))
455 {
456
457 /* Energy constraint fulfilled => use both vectors and scale them accordingly */
458 w16_en2Scale = 16 - WebRtcSpl_NormW32(w32_en2);
459 w16_en2Scale = WEBRTC_SPL_MAX(0, w16_en2Scale);
460 w16_en1Scale = w16_en2Scale - 13;
461
462 /* calculate w32_en1/w32_en2 in Q13 */
463 w32_en1_mul_en2 = WebRtcSpl_DivW32W16(
464 WEBRTC_SPL_SHIFT_W32(w32_en1, -w16_en1Scale),
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000465 (int16_t) (WEBRTC_SPL_RSHIFT_W32(w32_en2, w16_en2Scale)));
niklase@google.com470e71d2011-07-07 08:21:25 +0000466
467 /* calculate factor in Q13 (sqrt of en1/en2 in Q26) */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000468 w16_factor = (int16_t) WebRtcSpl_SqrtFloor(
niklase@google.com470e71d2011-07-07 08:21:25 +0000469 WEBRTC_SPL_LSHIFT_W32(w32_en1_mul_en2, 13));
470
471 /* Copy the two vectors and give them the same energy */
472
473 WEBRTC_SPL_MEMCPY_W16(ExpandState->pw16_expVecs[0], pw16_vec1, w16_expVecsLen);
474 WebRtcSpl_AffineTransformVector(ExpandState->pw16_expVecs[1], pw16_vec2,
475 w16_factor, 4096, 13, w16_expVecsLen);
476
477 }
478 else
479 {
480 /* Energy change constraint not fulfilled => only use last vector */
481
482 WEBRTC_SPL_MEMCPY_W16(ExpandState->pw16_expVecs[0], pw16_vec1, w16_expVecsLen);
483 WEBRTC_SPL_MEMCPY_W16(ExpandState->pw16_expVecs[1], ExpandState->pw16_expVecs[0],
484 w16_expVecsLen);
485
486 /* Set the w16_factor since it is used by muting slope */
487 if (((w32_en1 >> 2) < w32_en2) || (w32_en2 == 0))
488 {
489 w16_factor = 4096; /* 0.5 in Q13*/
490 }
491 else
492 {
493 w16_factor = 16384; /* 2.0 in Q13*/
494 }
495 }
496
497 /* Set the 3 lag values */
498 w16_diffLag = w16_DistLag - w16_CorrLag;
499 if (w16_diffLag == 0)
500 {
501 /* DistLag and CorrLag are equal */
502 ExpandState->w16_lags[0] = w16_DistLag;
503 ExpandState->w16_lags[1] = w16_DistLag;
504 ExpandState->w16_lags[2] = w16_DistLag;
505 }
506 else
507 {
508 /* DistLag and CorrLag are not equal; use different combinations of the two */
509 ExpandState->w16_lags[0] = w16_DistLag; /* DistLag only */
510 ExpandState->w16_lags[1] = ((w16_DistLag + w16_CorrLag) >> 1); /* 50/50 */
511 /* Third lag, move one half-step towards CorrLag (in both cases) */
512 if (w16_diffLag > 0)
513 {
514 ExpandState->w16_lags[2] = (w16_DistLag + w16_CorrLag - 1) >> 1;
515 }
516 else
517 {
518 ExpandState->w16_lags[2] = (w16_DistLag + w16_CorrLag + 1) >> 1;
519 }
520 }
521
522 /*************************************************
523 * Calculate the LPC and the gain of the filters *
524 *************************************************/
525
526 /* Calculate scale value needed for autocorrelation */
527 w16_tmp = WebRtcSpl_MaxAbsValueW16(
528 &(inst->pw16_speechHistory[inst->w16_speechHistoryLen - fsMultLPCAnalasysLen]),
529 fsMultLPCAnalasysLen);
530
531 w16_tmp = 16 - WebRtcSpl_NormW32(w16_tmp);
532 w16_tmp = WEBRTC_SPL_MIN(w16_tmp,0);
533 w16_tmp = (w16_tmp << 1) + 7;
534 w16_tmp = WEBRTC_SPL_MAX(w16_tmp,0);
535
536 /* set w16_ind to simplify the following expressions */
537 w16_ind = inst->w16_speechHistoryLen - fsMultLPCAnalasysLen - UNVOICED_LPC_ORDER;
538
539 /* store first UNVOICED_LPC_ORDER samples in pw16_rc */
540
541 WEBRTC_SPL_MEMCPY_W16(pw16_rc, &inst->pw16_speechHistory[w16_ind], UNVOICED_LPC_ORDER);
542
543 /* set first samples to zero */
544 WebRtcSpl_MemSetW16(&inst->pw16_speechHistory[w16_ind], 0, UNVOICED_LPC_ORDER);
545
546 /* Calculate UNVOICED_LPC_ORDER+1 lags of the ACF */
547
548 WebRtcNetEQ_CrossCorr(
549 pw32_autoCorr, &(inst->pw16_speechHistory[w16_ind + UNVOICED_LPC_ORDER]),
550 &(inst->pw16_speechHistory[w16_ind + UNVOICED_LPC_ORDER]), fsMultLPCAnalasysLen,
551 UNVOICED_LPC_ORDER + 1, w16_tmp, -1);
552
553 /* Recover the stored samples from pw16_rc */
554
555 WEBRTC_SPL_MEMCPY_W16(&inst->pw16_speechHistory[w16_ind], pw16_rc, UNVOICED_LPC_ORDER);
556
557 if (pw32_autoCorr[0] > 0)
558 { /* check that variance is positive */
559
560 /* estimate AR filter parameters using Levinson-Durbin algorithm
561 (UNVOICED_LPC_ORDER+1 filter coefficients) */
562 stability = WebRtcSpl_LevinsonDurbin(pw32_autoCorr, ExpandState->pw16_arFilter,
563 pw16_rc, UNVOICED_LPC_ORDER);
564
565 /* Only update BGN if filter is stable */
566 if (stability != 1)
567 {
568 /* Set first coefficient to 4096 (1.0 in Q12)*/
569 ExpandState->pw16_arFilter[0] = 4096;
570 /* Set remaining UNVOICED_LPC_ORDER coefficients to zero */
571 WebRtcSpl_MemSetW16(ExpandState->pw16_arFilter + 1, 0, UNVOICED_LPC_ORDER);
572 }
573
574 }
575
576 if (w16_DistLag < 40)
577 {
578 w16_energyLen = 2 * w16_DistLag;
579 }
580 else
581 {
582 w16_energyLen = w16_DistLag;
583 }
584 w16_randLen = w16_energyLen + 30; /* Startup part */
585
586 /* Extract a noise segment */
587 if (w16_randLen <= RANDVEC_NO_OF_SAMPLES)
588 {
589 WEBRTC_SPL_MEMCPY_W16(pw16_randVec,
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000590 (int16_t*) WebRtcNetEQ_kRandnTbl, w16_randLen);
niklase@google.com470e71d2011-07-07 08:21:25 +0000591 }
592 else
593 { /* only applies to SWB where length could be larger than 256 */
henrik.lundin@webrtc.org598ad062011-12-07 11:52:09 +0000594#if FSMULT >= 2 /* Makes pw16_randVec longer than RANDVEC_NO_OF_SAMPLES. */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000595 WEBRTC_SPL_MEMCPY_W16(pw16_randVec, (int16_t*) WebRtcNetEQ_kRandnTbl,
niklase@google.com470e71d2011-07-07 08:21:25 +0000596 RANDVEC_NO_OF_SAMPLES);
597 inst->w16_seedInc = (inst->w16_seedInc + 2) & (RANDVEC_NO_OF_SAMPLES - 1);
henrik.lundin@webrtc.org598ad062011-12-07 11:52:09 +0000598 assert(w16_randLen <= FSMULT * 120 + 30);
niklase@google.com470e71d2011-07-07 08:21:25 +0000599 WebRtcNetEQ_RandomVec(&inst->uw16_seed, &pw16_randVec[RANDVEC_NO_OF_SAMPLES],
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000600 (int16_t) (w16_randLen - RANDVEC_NO_OF_SAMPLES), inst->w16_seedInc);
henrik.lundin@webrtc.org598ad062011-12-07 11:52:09 +0000601#else
602 assert(0);
603#endif
niklase@google.com470e71d2011-07-07 08:21:25 +0000604 }
605
606 /* Set up state vector and calculate scale factor for unvoiced filtering */
607
608 WEBRTC_SPL_MEMCPY_W16(ExpandState->pw16_arState,
609 &(inst->pw16_speechHistory[inst->w16_speechHistoryLen - UNVOICED_LPC_ORDER]),
610 UNVOICED_LPC_ORDER);
611 WEBRTC_SPL_MEMCPY_W16(pw16_unvoicedVec - UNVOICED_LPC_ORDER,
612 &(inst->pw16_speechHistory[inst->w16_speechHistoryLen - 128 - UNVOICED_LPC_ORDER]),
613 UNVOICED_LPC_ORDER);
614 WebRtcSpl_FilterMAFastQ12(&inst->pw16_speechHistory[inst->w16_speechHistoryLen - 128],
615 pw16_unvoicedVec, ExpandState->pw16_arFilter, UNVOICED_LPC_ORDER + 1, 128);
616 if (WebRtcSpl_MaxAbsValueW16(pw16_unvoicedVec, 128) > 4000)
617 {
618 w16_scale = 4;
619 }
620 else
621 {
622 w16_scale = 0;
623 }
624 w32_tmp = WebRtcNetEQ_DotW16W16(pw16_unvoicedVec, pw16_unvoicedVec, 128, w16_scale);
625
626 /* Normalize w32_tmp to 28 or 29 bits to preserve sqrt() accuracy */
627 w16_tmp = WebRtcSpl_NormW32(w32_tmp) - 3;
628 w16_tmp += ((w16_tmp & 0x1) ^ 0x1); /* Make sure we do an odd number of shifts since we
629 from earlier have 7 shifts from dividing with 128.*/
630 w32_tmp = WEBRTC_SPL_SHIFT_W32(w32_tmp, w16_tmp);
henrik.lundin@webrtc.org9f710d02011-09-12 16:44:37 +0000631 w32_tmp = WebRtcSpl_SqrtFloor(w32_tmp);
niklase@google.com470e71d2011-07-07 08:21:25 +0000632 ExpandState->w16_arGainScale = 13 + ((w16_tmp + 7 - w16_scale) >> 1);
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000633 ExpandState->w16_arGain = (int16_t) w32_tmp;
niklase@google.com470e71d2011-07-07 08:21:25 +0000634
635 /********************************************************************
636 * Calculate vfraction from bestcorr *
637 * if (bestcorr>0.480665) *
638 * vfraction = ((bestcorr-0.4)/(1-0.4)).^2 *
639 * else vfraction = 0 *
640 * *
641 * approximation (coefficients in Q12): *
642 * if (x>0.480665) (y(x)<0.3) *
643 * y(x) = -1.264421 + 4.8659148*x - 4.0092827*x^2 + 1.4100529*x^3 *
644 * else y(x) = 0; *
645 ********************************************************************/
646
647 if (w16_bestcorr > 7875)
648 {
649 /* if x>0.480665 */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000650 int16_t w16_x1, w16_x2, w16_x3;
niklase@google.com470e71d2011-07-07 08:21:25 +0000651 w16_x1 = w16_bestcorr;
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000652 w32_tmp = WEBRTC_SPL_MUL_16_16((int32_t) w16_x1, w16_x1);
653 w16_x2 = (int16_t) WEBRTC_SPL_RSHIFT_W32(w32_tmp, 14);
niklase@google.com470e71d2011-07-07 08:21:25 +0000654 w32_tmp = WEBRTC_SPL_MUL_16_16(w16_x1, w16_x2);
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000655 w16_x3 = (int16_t) WEBRTC_SPL_RSHIFT_W32(w32_tmp, 14);
niklase@google.com470e71d2011-07-07 08:21:25 +0000656 w32_tmp
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000657 = (int32_t) WEBRTC_SPL_LSHIFT_W32((int32_t) WebRtcNetEQ_kMixFractionFuncTbl[0], 14);
niklase@google.com470e71d2011-07-07 08:21:25 +0000658 w32_tmp
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000659 += (int32_t) WEBRTC_SPL_MUL_16_16(WebRtcNetEQ_kMixFractionFuncTbl[1], w16_x1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000660 w32_tmp
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000661 += (int32_t) WEBRTC_SPL_MUL_16_16(WebRtcNetEQ_kMixFractionFuncTbl[2], w16_x2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000662 w32_tmp
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000663 += (int32_t) WEBRTC_SPL_MUL_16_16(WebRtcNetEQ_kMixFractionFuncTbl[3], w16_x3);
664 ExpandState->w16_vFraction = (int16_t) WEBRTC_SPL_RSHIFT_W32(w32_tmp, 12);
niklase@google.com470e71d2011-07-07 08:21:25 +0000665 ExpandState->w16_vFraction = WEBRTC_SPL_MIN(ExpandState->w16_vFraction, 16384);
666 ExpandState->w16_vFraction = WEBRTC_SPL_MAX(ExpandState->w16_vFraction, 0);
667 }
668 else
669 {
670 ExpandState->w16_vFraction = 0;
671 }
672
673 /***********************************************************************
674 * Calculate muting slope, reuse value from earlier scaling of ExpVecs *
675 ***********************************************************************/
676 w16_slope = w16_factor;
677
678 if (w16_slope > 12288)
679 {
680 /* w16_slope > 1.5 ? */
681 /* Calculate (1-(1/slope))/w16_DistLag = (slope-1)/(w16_DistLag*slope) */
682 w32_tmp = w16_slope - 8192;
683 w32_tmp = WEBRTC_SPL_LSHIFT_W32(w32_tmp, 12); /* Value in Q25 (13+12=25) */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000684 w16_tmp = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(w16_DistLag,
niklase@google.com470e71d2011-07-07 08:21:25 +0000685 w16_slope, 8); /* Value in Q5 (13-8=5) */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000686 w16_tmp = (int16_t) WebRtcSpl_DivW32W16(w32_tmp,
niklase@google.com470e71d2011-07-07 08:21:25 +0000687 w16_tmp); /* Res in Q20 (25-5=20) */
688
689 if (w16_slope > 14746)
690 { /* w16_slope > 1.8 ? */
691 ExpandState->w16_muteSlope = (w16_tmp + 1) >> 1;
692 }
693 else
694 {
695 ExpandState->w16_muteSlope = (w16_tmp + 4) >> 3;
696 }
697 ExpandState->w16_onset = 1;
698 }
699 else if (ExpandState->w16_vFraction > 13107)
700 {
701 /* w16_vFraction > 0.8 ? */
702 if (w16_slope > 8028)
703 {
704 /* w16_vFraction > 0.98 ? */
705 ExpandState->w16_muteSlope = 0;
706 }
707 else
708 {
709 /* Calculate (1-slope)/w16_DistLag */
710 w32_tmp = 8192 - w16_slope;
711 w32_tmp = WEBRTC_SPL_LSHIFT_W32(w32_tmp, 7); /* Value in Q20 (13+7=20) */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000712 ExpandState->w16_muteSlope = (int16_t) WebRtcSpl_DivW32W16(w32_tmp,
niklase@google.com470e71d2011-07-07 08:21:25 +0000713 w16_DistLag); /* Res in Q20 (20-0=20) */
714 }
715 ExpandState->w16_onset = 0;
716 }
717 else
718 {
719 /*
720 * Use the minimum of 0.005 (0.9 on 50 samples in NB and the slope)
721 * and ((1-slope)/w16_DistLag)
722 */
723 w32_tmp = 8192 - w16_slope;
724 w32_tmp = WEBRTC_SPL_LSHIFT_W32(w32_tmp, 7); /* Value in Q20 (13+7=20) */
725 w32_tmp = WEBRTC_SPL_MAX(w32_tmp, 0);
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000726 ExpandState->w16_muteSlope = (int16_t) WebRtcSpl_DivW32W16(w32_tmp,
niklase@google.com470e71d2011-07-07 08:21:25 +0000727 w16_DistLag); /* Res in Q20 (20-0=20) */
728 w16_tmp = WebRtcNetEQ_k5243div[fs_mult]; /* 0.005/fs_mult = 5243/fs_mult */
729 ExpandState->w16_muteSlope = WEBRTC_SPL_MAX(w16_tmp, ExpandState->w16_muteSlope);
730 ExpandState->w16_onset = 0;
731 }
732 }
733 else
734 {
735 /* This is not the first Expansion, parameters are already estimated. */
736
737 /* Extract a noise segment */
738 if (BGNonly) /* If we should produce nothing but background noise */
739 {
740 if (*pw16_len > 0)
741 {
742 /*
743 * Set length to input parameter length, but not more than length
744 * of pw16_randVec
745 */
746 w16_lag = WEBRTC_SPL_MIN(*pw16_len, FSMULT * 120 + 30);
747 }
748 else
749 {
750 /* set length to 15 ms */
751 w16_lag = fsMult120;
752 }
753 w16_randLen = w16_lag;
754 }
755 else
756 {
757 w16_randLen = ExpandState->w16_maxLag;
758 }
759
760 if (w16_randLen <= RANDVEC_NO_OF_SAMPLES)
761 {
762 inst->w16_seedInc = (inst->w16_seedInc + 2) & (RANDVEC_NO_OF_SAMPLES - 1);
763 WebRtcNetEQ_RandomVec(&inst->uw16_seed, pw16_randVec, w16_randLen,
764 inst->w16_seedInc);
765 }
766 else
767 { /* only applies to SWB where length could be larger than 256 */
henrik.lundin@webrtc.org598ad062011-12-07 11:52:09 +0000768#if FSMULT >= 2 /* Makes pw16_randVec longer than RANDVEC_NO_OF_SAMPLES. */
niklase@google.com470e71d2011-07-07 08:21:25 +0000769 inst->w16_seedInc = (inst->w16_seedInc + 2) & (RANDVEC_NO_OF_SAMPLES - 1);
770 WebRtcNetEQ_RandomVec(&inst->uw16_seed, pw16_randVec, RANDVEC_NO_OF_SAMPLES,
771 inst->w16_seedInc);
772 inst->w16_seedInc = (inst->w16_seedInc + 2) & (RANDVEC_NO_OF_SAMPLES - 1);
henrik.lundin@webrtc.org598ad062011-12-07 11:52:09 +0000773 assert(w16_randLen <= FSMULT * 120 + 30);
niklase@google.com470e71d2011-07-07 08:21:25 +0000774 WebRtcNetEQ_RandomVec(&inst->uw16_seed, &pw16_randVec[RANDVEC_NO_OF_SAMPLES],
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000775 (int16_t) (w16_randLen - RANDVEC_NO_OF_SAMPLES), inst->w16_seedInc);
henrik.lundin@webrtc.org598ad062011-12-07 11:52:09 +0000776#else
777 assert(0);
778#endif
niklase@google.com470e71d2011-07-07 08:21:25 +0000779 }
780 } /* end if(first expand or BGNonly) ... else ... */
781
782 if (!BGNonly) /* Voiced and unvoiced parts not used if generating BGN only */
783 {
784
785 /*************************************************
786 * Generate signal *
787 *************************************************/
788
789 /*
790 * Voiced part
791 */
792
793 /* Linearly mute the use_vfraction value from 1 to vfraction */
794 if (ExpandState->w16_consecExp == 0)
795 {
796 ExpandState->w16_currentVFraction = 16384; /* 1.0 in Q14 */
797 }
798
799 ExpandState->w16_lagsPosition = ExpandState->w16_lagsPosition
800 + ExpandState->w16_lagsDirection;
801
802 /* Change direction if needed */
803 if (ExpandState->w16_lagsPosition == 0)
804 {
805 ExpandState->w16_lagsDirection = 1;
806 }
807 if (ExpandState->w16_lagsPosition == 2)
808 {
809 ExpandState->w16_lagsDirection = -1;
810 }
811
812 /* Generate a weighted vector with the selected lag */
813 w16_expVecsLen = ExpandState->w16_maxLag + ExpandState->w16_overlap;
814 w16_lag = ExpandState->w16_lags[ExpandState->w16_lagsPosition];
815 /* Copy lag+overlap data */
816 w16_expVecPos = w16_expVecsLen - w16_lag - ExpandState->w16_overlap;
817 w16_tmp = w16_lag + ExpandState->w16_overlap;
818 if (ExpandState->w16_lagsPosition == 0)
819 {
820 WEBRTC_SPL_MEMCPY_W16(pw16_voicedVecStorage,
821 &(ExpandState->pw16_expVecs[0][w16_expVecPos]), w16_tmp);
822 }
823 else if (ExpandState->w16_lagsPosition == 1)
824 {
825 WebRtcSpl_ScaleAndAddVectorsWithRound(&ExpandState->pw16_expVecs[0][w16_expVecPos], 3,
826 &ExpandState->pw16_expVecs[1][w16_expVecPos], 1, 2, pw16_voicedVecStorage,
827 w16_tmp);
828
829 }
830 else if (ExpandState->w16_lagsPosition == 2)
831 {
832 WebRtcSpl_ScaleAndAddVectorsWithRound(&ExpandState->pw16_expVecs[0][w16_expVecPos], 1,
833 &ExpandState->pw16_expVecs[1][w16_expVecPos], 1, 1, pw16_voicedVecStorage,
834 w16_tmp);
835 }
836
837 if (inst->fs == 8000)
838 {
839 /* Windowing in Q15 */
840 w16_winMute = NETEQ_OVERLAP_WINMUTE_8KHZ_START;
841 w16_winMuteInc = NETEQ_OVERLAP_WINMUTE_8KHZ_INC;
842 w16_winUnMute = NETEQ_OVERLAP_WINUNMUTE_8KHZ_START;
843 w16_winUnMuteInc = NETEQ_OVERLAP_WINUNMUTE_8KHZ_INC;
844#ifdef NETEQ_WIDEBAND
845 }
846 else if (inst->fs == 16000)
847 {
848 /* Windowing in Q15 */
849 w16_winMute = NETEQ_OVERLAP_WINMUTE_16KHZ_START;
850 w16_winMuteInc = NETEQ_OVERLAP_WINMUTE_16KHZ_INC;
851 w16_winUnMute = NETEQ_OVERLAP_WINUNMUTE_16KHZ_START;
852 w16_winUnMuteInc = NETEQ_OVERLAP_WINUNMUTE_16KHZ_INC;
853#endif
854#ifdef NETEQ_32KHZ_WIDEBAND
855 }
856 else if (inst->fs == 32000)
857 {
858 /* Windowing in Q15 */
859 w16_winMute = NETEQ_OVERLAP_WINMUTE_32KHZ_START;
860 w16_winMuteInc = NETEQ_OVERLAP_WINMUTE_32KHZ_INC;
861 w16_winUnMute = NETEQ_OVERLAP_WINUNMUTE_32KHZ_START;
862 w16_winUnMuteInc = NETEQ_OVERLAP_WINUNMUTE_32KHZ_INC;
863#endif
864#ifdef NETEQ_48KHZ_WIDEBAND
865 }
866 else /* if (inst->fs==48000) */
867 {
868 /* Windowing in Q15 */
869 w16_winMute = NETEQ_OVERLAP_WINMUTE_48KHZ_START;
870 w16_winMuteInc = NETEQ_OVERLAP_WINMUTE_48KHZ_INC;
871 w16_winUnMute = NETEQ_OVERLAP_WINUNMUTE_48KHZ_START;
872 w16_winUnMuteInc = NETEQ_OVERLAP_WINUNMUTE_48KHZ_INC;
873#endif
874 }
875
876 /* Smooth the expanded if it has not been muted to or vfraction is larger than 0.5 */
877 if ((ExpandState->w16_expandMuteFactor > 819) && (ExpandState->w16_currentVFraction
878 > 8192))
879 {
880 for (i = 0; i < ExpandState->w16_overlap; i++)
881 {
882 /* Do overlap add between new vector and overlap */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000883 ExpandState->pw16_overlapVec[i] = (int16_t) WEBRTC_SPL_RSHIFT_W32(
niklase@google.com470e71d2011-07-07 08:21:25 +0000884 WEBRTC_SPL_MUL_16_16(ExpandState->pw16_overlapVec[i], w16_winMute) +
885 WEBRTC_SPL_MUL_16_16(
886 WEBRTC_SPL_MUL_16_16_RSFT(ExpandState->w16_expandMuteFactor,
887 pw16_voicedVecStorage[i], 14), w16_winUnMute) + 16384, 15);
888 w16_winMute += w16_winMuteInc;
889 w16_winUnMute += w16_winUnMuteInc;
890 }
891 }
892 else if (ExpandState->w16_expandMuteFactor == 0
893#ifdef NETEQ_STEREO
894 && msInfo->msMode == NETEQ_MONO /* only if mono mode is selected */
895#endif
896 )
897 {
898 /* if ExpandState->w16_expandMuteFactor = 0 => all is CNG component
899 set the output length to 15ms (for best CNG production) */
900 w16_tmp = fsMult120;
901 ExpandState->w16_maxLag = w16_tmp;
902 ExpandState->w16_lags[0] = w16_tmp;
903 ExpandState->w16_lags[1] = w16_tmp;
904 ExpandState->w16_lags[2] = w16_tmp;
905 }
906
907 /*
908 * Unvoiced part
909 */
910
911 WEBRTC_SPL_MEMCPY_W16(pw16_unvoicedVec - UNVOICED_LPC_ORDER,
912 ExpandState->pw16_arState,
913 UNVOICED_LPC_ORDER);
914 if (ExpandState->w16_arGainScale > 0)
915 {
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000916 w32_tmp = ((int32_t) 1) << (ExpandState->w16_arGainScale - 1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000917 }
918 else
919 {
920 w32_tmp = 0;
921 }
922
923 /* Note that shift value can be >16 which complicates things for some DSPs */
924 WebRtcSpl_AffineTransformVector(pw16_scaledRandVec, pw16_randVec,
925 ExpandState->w16_arGain, w32_tmp, ExpandState->w16_arGainScale, w16_lag);
926
927 WebRtcSpl_FilterARFastQ12(pw16_scaledRandVec, pw16_unvoicedVec,
928 ExpandState->pw16_arFilter, UNVOICED_LPC_ORDER + 1, w16_lag);
929
930 WEBRTC_SPL_MEMCPY_W16(ExpandState->pw16_arState,
931 &(pw16_unvoicedVec[w16_lag - UNVOICED_LPC_ORDER]),
932 UNVOICED_LPC_ORDER);
933
934 /*
935 * Voiced + Unvoiced
936 */
937
938 /* For lag =
939 <=31*fs_mult => go from 1 to 0 in about 8 ms
940 (>=31..<=63)*fs_mult => go from 1 to 0 in about 16 ms
941 >=64*fs_mult => go from 1 to 0 in about 32 ms
942 */
943 w16_tmp = (31 - WebRtcSpl_NormW32(ExpandState->w16_maxLag)) - 5; /* getbits(w16_maxLag) -5 */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000944 w16_vfractionChange = (int16_t) WEBRTC_SPL_RSHIFT_W32(256, w16_tmp);
niklase@google.com470e71d2011-07-07 08:21:25 +0000945 if (ExpandState->w16_stopMuting == 1)
946 {
947 w16_vfractionChange = 0;
948 }
949
950 /* Create combined signal (unmuted) by shifting in more and more of unvoiced part */
951 w16_tmp = 8 - w16_tmp; /* getbits(w16_vfractionChange) */
952 w16_tmp = (ExpandState->w16_currentVFraction - ExpandState->w16_vFraction) >> w16_tmp;
953 w16_tmp = WEBRTC_SPL_MIN(w16_tmp, w16_lag);
954 WebRtcNetEQ_MixVoiceUnvoice(pw16_outData, pw16_voicedVec, pw16_unvoicedVec,
955 &ExpandState->w16_currentVFraction, w16_vfractionChange, w16_tmp);
956
957 if (w16_tmp < w16_lag)
958 {
959 if (w16_vfractionChange != 0)
960 {
961 ExpandState->w16_currentVFraction = ExpandState->w16_vFraction;
962 }
963 w16_tmp2 = 16384 - ExpandState->w16_currentVFraction;
964 WebRtcSpl_ScaleAndAddVectorsWithRound(pw16_voicedVec + w16_tmp,
965 ExpandState->w16_currentVFraction, pw16_unvoicedVec + w16_tmp, w16_tmp2, 14,
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000966 pw16_outData + w16_tmp, (int16_t) (w16_lag - w16_tmp));
niklase@google.com470e71d2011-07-07 08:21:25 +0000967 }
968
969 /* Select muting factor */
970 if (ExpandState->w16_consecExp == 3)
971 {
972 /* 0.95 on 50 samples in NB (0.0010/fs_mult in Q20) */
973 ExpandState->w16_muteSlope = WEBRTC_SPL_MAX(ExpandState->w16_muteSlope,
974 WebRtcNetEQ_k1049div[fs_mult]);
975 }
976 if (ExpandState->w16_consecExp == 7)
977 {
978 /* 0.90 on 50 samples in NB (0.0020/fs_mult in Q20) */
979 ExpandState->w16_muteSlope = WEBRTC_SPL_MAX(ExpandState->w16_muteSlope,
980 WebRtcNetEQ_k2097div[fs_mult]);
981 }
982
983 /* Mute segment according to slope value */
984 if ((ExpandState->w16_consecExp != 0) || (ExpandState->w16_onset != 1))
985 {
986 /* Mute to the previous level, then continue with the muting */
987 WebRtcSpl_AffineTransformVector(pw16_outData, pw16_outData,
988 ExpandState->w16_expandMuteFactor, 8192, 14, w16_lag);
989
990 if ((ExpandState->w16_stopMuting != 1))
991 {
992 WebRtcNetEQ_MuteSignal(pw16_outData, ExpandState->w16_muteSlope, w16_lag);
993
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000994 w16_tmp = 16384 - (int16_t) ((WEBRTC_SPL_MUL_16_16(w16_lag,
niklase@google.com470e71d2011-07-07 08:21:25 +0000995 ExpandState->w16_muteSlope) + 8192) >> 6); /* 20-14 = 6 */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000996 w16_tmp = (int16_t) ((WEBRTC_SPL_MUL_16_16(w16_tmp,
niklase@google.com470e71d2011-07-07 08:21:25 +0000997 ExpandState->w16_expandMuteFactor) + 8192) >> 14);
998
999 /* Guard against getting stuck with very small (but sometimes audible) gain */
1000 if ((ExpandState->w16_consecExp > 3) && (w16_tmp
1001 >= ExpandState->w16_expandMuteFactor))
1002 {
1003 ExpandState->w16_expandMuteFactor = 0;
1004 }
1005 else
1006 {
1007 ExpandState->w16_expandMuteFactor = w16_tmp;
1008 }
1009 }
1010 }
1011
1012 } /* end if(!BGNonly) */
1013
1014 /*
1015 * BGN
1016 */
1017
1018 if (BGNState->w16_initialized == 1)
1019 {
1020 /* BGN parameters are initialized; use them */
1021
1022 WEBRTC_SPL_MEMCPY_W16(pw16_cngVec - BGN_LPC_ORDER,
1023 BGNState->pw16_filterState,
1024 BGN_LPC_ORDER);
1025
1026 if (BGNState->w16_scaleShift > 1)
1027 {
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001028 w32_tmp = ((int32_t) 1) << (BGNState->w16_scaleShift - 1);
niklase@google.com470e71d2011-07-07 08:21:25 +00001029 }
1030 else
1031 {
1032 w32_tmp = 0;
1033 }
1034
1035 /* Scale random vector to correct energy level */
1036 /* Note that shift value can be >16 which complicates things for some DSPs */
1037 WebRtcSpl_AffineTransformVector(pw16_scaledRandVec, pw16_randVec,
1038 BGNState->w16_scale, w32_tmp, BGNState->w16_scaleShift, w16_lag);
1039
1040 WebRtcSpl_FilterARFastQ12(pw16_scaledRandVec, pw16_cngVec, BGNState->pw16_filter,
1041 BGN_LPC_ORDER + 1, w16_lag);
1042
1043 WEBRTC_SPL_MEMCPY_W16(BGNState->pw16_filterState,
1044 &(pw16_cngVec[w16_lag-BGN_LPC_ORDER]),
1045 BGN_LPC_ORDER);
1046
1047 /* Unmute the insertion of background noise */
1048
1049 if (bgnMode == BGN_FADE && ExpandState->w16_consecExp >= FADE_BGN_TIME
1050 && BGNState->w16_mutefactor > 0)
1051 {
1052 /* fade BGN to zero */
1053 /* calculate muting slope, approx 2^18/fsHz */
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001054 int16_t muteFactor;
niklase@google.com470e71d2011-07-07 08:21:25 +00001055 if (fs_mult == 1)
1056 {
1057 muteFactor = -32;
1058 }
1059 else if (fs_mult == 2)
1060 {
1061 muteFactor = -16;
1062 }
1063 else if (fs_mult == 4)
1064 {
1065 muteFactor = -8;
1066 }
1067 else
1068 {
1069 muteFactor = -5;
1070 }
1071 /* use UnmuteSignal function with negative slope */
1072 WebRtcNetEQ_UnmuteSignal(pw16_cngVec, &BGNState->w16_mutefactor, /* In Q14 */
1073 pw16_cngVec, muteFactor, /* In Q20 */
1074 w16_lag);
1075 }
1076 else if (BGNState->w16_mutefactor < 16384 && !BGNonly)
1077 {
1078 /* if (w16_mutefactor < 1) and not BGN only (since then we use no muting) */
1079
1080 /*
1081 * If BGN_OFF, or if BNG_FADE has started fading,
1082 * mutefactor should not be increased.
1083 */
1084 if (ExpandState->w16_stopMuting != 1 && bgnMode != BGN_OFF && !(bgnMode
1085 == BGN_FADE && ExpandState->w16_consecExp >= FADE_BGN_TIME))
1086 {
1087 WebRtcNetEQ_UnmuteSignal(pw16_cngVec, &BGNState->w16_mutefactor, /* In Q14 */
1088 pw16_cngVec, ExpandState->w16_muteSlope, /* In Q20 */
1089 w16_lag);
1090 }
1091 else
1092 {
1093 /* BGN_ON and stop muting, or
1094 * BGN_OFF (mute factor is always 0), or
1095 * BGN_FADE has reached 0 */
1096 WebRtcSpl_AffineTransformVector(pw16_cngVec, pw16_cngVec,
1097 BGNState->w16_mutefactor, 8192, 14, w16_lag);
1098 }
1099 }
1100 }
1101 else
1102 {
1103 /* BGN parameters have not been initialized; use zero noise */
1104 WebRtcSpl_MemSetW16(pw16_cngVec, 0, w16_lag);
1105 }
1106
1107 if (BGNonly)
1108 {
1109 /* Copy BGN to outdata */
1110 for (i = 0; i < w16_lag; i++)
1111 {
1112 pw16_outData[i] = pw16_cngVec[i];
1113 }
1114 }
1115 else
1116 {
1117 /* Add CNG vector to the Voiced + Unvoiced vectors */
1118 for (i = 0; i < w16_lag; i++)
1119 {
1120 pw16_outData[i] = pw16_outData[i] + pw16_cngVec[i];
1121 }
1122
1123 /* increase call number */
1124 ExpandState->w16_consecExp = ExpandState->w16_consecExp + 1;
1125 if (ExpandState->w16_consecExp < 0) /* Guard against overflow */
1126 ExpandState->w16_consecExp = FADE_BGN_TIME; /* "Arbitrary" large num of expands */
1127 }
1128
1129 inst->w16_mode = MODE_EXPAND;
1130 *pw16_len = w16_lag;
1131
1132 /* Update in-call and post-call statistics */
1133 if (ExpandState->w16_stopMuting != 1 || BGNonly)
1134 {
1135 /*
1136 * Only do this if StopMuting != 1 or if explicitly BGNonly, otherwise Expand is
1137 * called from Merge or Normal and special measures must be taken.
1138 */
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001139 inst->statInst.expandLength += (uint32_t) *pw16_len;
niklase@google.com470e71d2011-07-07 08:21:25 +00001140 if (ExpandState->w16_expandMuteFactor == 0 || BGNonly)
1141 {
1142 /* Only noise expansion */
1143 inst->statInst.expandedNoiseSamples += *pw16_len;
turaj@webrtc.org92d1f072013-04-15 16:52:04 +00001144 /* Short-term activity statistics. */
1145 inst->activity_stats.expand_bgn_samples += *pw16_len;
niklase@google.com470e71d2011-07-07 08:21:25 +00001146 }
1147 else
1148 {
1149 /* Voice expand (note: not necessarily _voiced_) */
1150 inst->statInst.expandedVoiceSamples += *pw16_len;
turaj@webrtc.org92d1f072013-04-15 16:52:04 +00001151 /* Short-term activity statistics. */
1152 inst->activity_stats.expand_normal_samples += *pw16_len;
niklase@google.com470e71d2011-07-07 08:21:25 +00001153 }
1154 }
1155
1156 return 0;
1157}
1158
1159/****************************************************************************
1160 * WebRtcNetEQ_GenerateBGN(...)
1161 *
1162 * This function generates and writes len samples of background noise to the
1163 * output vector. The Expand function will be called repeatedly until the
1164 * correct number of samples is produced.
1165 *
1166 * Input:
1167 * - inst : NetEq instance, i.e. the user that requests more
1168 * speech/audio data
1169 * - scratchPtr : Pointer to scratch vector
1170 * - len : Desired length of produced BGN.
1171 *
1172 *
1173 * Output:
1174 * - pw16_outData : Pointer to a memory space where the output data
1175 * should be stored
1176 *
1177 * Return value : >=0 - Number of noise samples produced and written
1178 * to output
1179 * -1 - Error
1180 */
1181
1182int WebRtcNetEQ_GenerateBGN(DSPInst_t *inst,
1183#ifdef SCRATCH
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001184 int16_t *pw16_scratchPtr,
niklase@google.com470e71d2011-07-07 08:21:25 +00001185#endif
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001186 int16_t *pw16_outData, int16_t len)
niklase@google.com470e71d2011-07-07 08:21:25 +00001187{
1188
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001189 int16_t pos = 0;
1190 int16_t tempLen = len;
niklase@google.com470e71d2011-07-07 08:21:25 +00001191
1192 while (tempLen > 0)
1193 {
1194 /* while we still need more noise samples, call Expand to obtain background noise */
1195 WebRtcNetEQ_Expand(inst,
1196#ifdef SCRATCH
1197 pw16_scratchPtr,
1198#endif
1199 &pw16_outData[pos], &tempLen, 1 /*BGNonly*/);
1200
1201 pos += tempLen; /* we got this many samples */
1202 tempLen = len - pos; /* this is the number of samples we still need */
1203 }
1204
1205 return pos;
1206}
1207
1208#undef SCRATCH_PW16_BEST_CORR_INDEX
1209#undef SCRATCH_PW16_BEST_CORR
1210#undef SCRATCH_PW16_BEST_DIST_INDEX
1211#undef SCRATCH_PW16_BEST_DIST
1212#undef SCRATCH_PW16_CORR_VEC
1213#undef SCRATCH_PW16_CORR2
1214#undef SCRATCH_PW32_AUTO_CORR
1215#undef SCRATCH_PW16_RC
1216#undef SCRATCH_PW16_RAND_VEC
1217#undef SCRATCH_NETEQDSP_CORRELATOR
1218#undef SCRATCH_PW16_SCALED_RAND_VEC
1219#undef SCRATCH_PW16_UNVOICED_VEC_SPACE
1220