blob: 82c54ea30a92162676dfcda8ceb1f6bc2afb6e03 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
bjornv@webrtc.org152c34c2012-01-23 12:36:46 +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 some DSP initialization functions and
13 * constant table definitions.
14 */
15
16#include "dsp.h"
17
18#include "signal_processing_library.h"
19
20#include "neteq_error_codes.h"
21
22/* Filter coefficients used when downsampling from the indicated
23 sample rates (8, 16, 32, 48 kHz) to 4 kHz.
24 Coefficients are in Q12. */
25
26/* {0.3, 0.4, 0.3} */
27const WebRtc_Word16 WebRtcNetEQ_kDownsample8kHzTbl[] = { 1229, 1638, 1229 };
28
29#ifdef NETEQ_WIDEBAND
30/* {0.15, 0.2, 0.3, 0.2, 0.15} */
31const WebRtc_Word16 WebRtcNetEQ_kDownsample16kHzTbl[] =
32{ 614, 819, 1229, 819, 614};
33#endif
34
35#ifdef NETEQ_32KHZ_WIDEBAND
36/* {0.1425, 0.1251, 0.1525, 0.1628, 0.1525, 0.1251, 0.1425} */
37const WebRtc_Word16 WebRtcNetEQ_kDownsample32kHzTbl[] =
38{ 584, 512, 625, 667, 625, 512, 584};
39#endif
40
41#ifdef NETEQ_48KHZ_WIDEBAND
42/* {0.2487, 0.0952, 0.1042, 0.1074, 0.1042, 0.0952, 0.2487} */
43const WebRtc_Word16 WebRtcNetEQ_kDownsample48kHzTbl[] =
44{ 1019, 390, 427, 440, 427, 390, 1019};
45#endif
46
47/* Constants used in expand function WebRtcNetEQ_Expand */
48
49/* Q12: -1.264421 + 4.8659148*x - 4.0092827*x^2 + 1.4100529*x^3 */
50const WebRtc_Word16 WebRtcNetEQ_kMixFractionFuncTbl[4] = { -5179, 19931, -16422, 5776 };
51
52/* Tabulated divisions to save complexity */
53/* 1049/{0, .., 6} */
54const WebRtc_Word16 WebRtcNetEQ_k1049div[7] = { 0, 1049, 524, 349, 262, 209, 174 };
55
56/* 2097/{0, .., 6} */
57const WebRtc_Word16 WebRtcNetEQ_k2097div[7] = { 0, 2097, 1048, 699, 524, 419, 349 };
58
59/* 5243/{0, .., 6} */
60const WebRtc_Word16 WebRtcNetEQ_k5243div[7] = { 0, 5243, 2621, 1747, 1310, 1048, 873 };
61
62#ifdef WEBRTC_NETEQ_40BITACC_TEST
63/*
64 * Run NetEQ with simulated 40-bit accumulator to run bit-exact to a DSP
65 * implementation where the main (spl and NetEQ) functions have been
66 * 40-bit optimized. For testing purposes.
67 */
68
69/****************************************************************************
70 * WebRtcNetEQ_40BitAccCrossCorr(...)
71 *
72 * Calculates the Cross correlation between two sequences seq1 and seq2. Seq1
73 * is fixed and seq2 slides as the pointer is increased with step
74 *
75 * Input:
76 * - seq1 : First sequence (fixed throughout the correlation)
77 * - seq2 : Second sequence (slided step_seq2 for each
78 * new correlation)
79 * - dimSeq : Number of samples to use in the cross correlation.
80 * Should be no larger than 1024 to avoid overflow.
81 * - dimCrossCorr : Number of CrossCorrelations to calculate (start
82 * position for seq2 is updated for each new one)
83 * - rShift : Number of right shifts to use
84 * - step_seq2 : How many (positive or negative) steps the seq2
85 * pointer should be updated for each new cross
86 * correlation value
87 *
88 * Output:
89 * - crossCorr : The cross correlation in Q-rShift
90 */
91
92void WebRtcNetEQ_40BitAccCrossCorr(WebRtc_Word32 *crossCorr,
93 WebRtc_Word16 *seq1,
94 WebRtc_Word16 *seq2,
95 WebRtc_Word16 dimSeq,
96 WebRtc_Word16 dimCrossCorr,
97 WebRtc_Word16 rShift,
98 WebRtc_Word16 step_seq2)
99{
100 int i, j;
101 WebRtc_Word16 *seq1Ptr, *seq2Ptr;
102 WebRtc_Word64 acc;
103
104 for (i = 0; i < dimCrossCorr; i++)
105 {
106 /* Set the pointer to the static vector, set the pointer to
107 the sliding vector and initialize crossCorr */
108 seq1Ptr = seq1;
109 seq2Ptr = seq2 + (step_seq2 * i);
110 acc = 0;
111
112 /* Perform the cross correlation */
113 for (j = 0; j < dimSeq; j++)
114 {
115 acc += WEBRTC_SPL_MUL_16_16((*seq1Ptr), (*seq2Ptr));
116 seq1Ptr++;
117 seq2Ptr++;
118 }
119
120 (*crossCorr) = (WebRtc_Word32) (acc >> rShift);
121 crossCorr++;
122 }
123}
124
125/****************************************************************************
126 * WebRtcNetEQ_40BitAccDotW16W16(...)
127 *
128 * Calculates the dot product between two vectors (WebRtc_Word16)
129 *
130 * Input:
131 * - vector1 : Vector 1
132 * - vector2 : Vector 2
133 * - len : Number of samples in vector
134 * Should be no larger than 1024 to avoid overflow.
135 * - scaling : The number of left shifts required to avoid overflow
136 * in the dot product
137 * Return value : The dot product
138 */
139
140WebRtc_Word32 WebRtcNetEQ_40BitAccDotW16W16(WebRtc_Word16 *vector1,
141 WebRtc_Word16 *vector2,
142 int len,
143 int scaling)
144{
145 WebRtc_Word32 sum;
146 int i;
147 WebRtc_Word64 acc;
148
149 acc = 0;
150 for (i = 0; i < len; i++)
151 {
152 acc += WEBRTC_SPL_MUL_16_16(*vector1++, *vector2++);
153 }
154
155 sum = (WebRtc_Word32) (acc >> scaling);
156
157 return(sum);
158}
159
160#endif /* WEBRTC_NETEQ_40BITACC_TEST */
161
162/****************************************************************************
163 * WebRtcNetEQ_DSPInit(...)
164 *
165 * Initializes DSP side of NetEQ.
166 *
167 * Input:
168 * - inst : NetEq DSP instance
169 * - fs : Initial sample rate (may change when decoding data)
170 *
171 * Output:
172 * - inst : Updated instance
173 *
174 * Return value : 0 - ok
175 * : non-zero - error
176 */
177
178int WebRtcNetEQ_DSPInit(DSPInst_t *inst, WebRtc_UWord16 fs)
179{
180
181 int res = 0;
182 WebRtc_Word16 fs_mult;
183
184 /* Pointers and values to save before clearing the instance */
185#ifdef NETEQ_CNG_CODEC
186 void *savedPtr1 = inst->CNG_Codec_inst;
187#endif
188 void *savedPtr2 = inst->pw16_readAddress;
189 void *savedPtr3 = inst->pw16_writeAddress;
190 void *savedPtr4 = inst->main_inst;
191#ifdef NETEQ_VAD
192 void *savedVADptr = inst->VADInst.VADState;
193 VADInitFunction savedVADinit = inst->VADInst.initFunction;
194 VADSetmodeFunction savedVADsetmode = inst->VADInst.setmodeFunction;
195 VADFunction savedVADfunc = inst->VADInst.VADFunction;
196 WebRtc_Word16 savedVADEnabled = inst->VADInst.VADEnabled;
bjornv@webrtc.orgb38fca12012-06-19 11:03:32 +0000197 int savedVADMode = inst->VADInst.VADMode;
niklase@google.com470e71d2011-07-07 08:21:25 +0000198#endif /* NETEQ_VAD */
199 DSPStats_t saveStats;
200 WebRtc_Word16 saveMsPerCall = inst->millisecondsPerCall;
201 enum BGNMode saveBgnMode = inst->BGNInst.bgnMode;
202#ifdef NETEQ_STEREO
203 MasterSlaveInfo saveMSinfo;
204#endif
205
206 /* copy contents of statInst to avoid clearing */WEBRTC_SPL_MEMCPY_W16(&saveStats, &(inst->statInst),
207 sizeof(DSPStats_t)/sizeof(WebRtc_Word16));
208
209#ifdef NETEQ_STEREO
210 /* copy contents of msInfo to avoid clearing */WEBRTC_SPL_MEMCPY_W16(&saveMSinfo, &(inst->msInfo),
211 sizeof(MasterSlaveInfo)/sizeof(WebRtc_Word16));
212#endif
213
214 /* check that the sample rate is valid */
215 if ((fs != 8000)
216#ifdef NETEQ_WIDEBAND
217 &&(fs!=16000)
218#endif
219#ifdef NETEQ_32KHZ_WIDEBAND
220 &&(fs!=32000)
221#endif
222#ifdef NETEQ_48KHZ_WIDEBAND
223 &&(fs!=48000)
224#endif
225 )
226 {
227 /* invalid rate */
228 return (CODEC_DB_UNSUPPORTED_FS);
229 }
230
231 /* calcualte fs/8000 */
232 fs_mult = WebRtcSpl_DivW32W16ResW16(fs, 8000);
233
234 /* Set everything to zero since most variables should be zero at start */
235 WebRtcSpl_MemSetW16((WebRtc_Word16 *) inst, 0, sizeof(DSPInst_t) / sizeof(WebRtc_Word16));
236
237 /* Restore saved pointers */
238#ifdef NETEQ_CNG_CODEC
239 inst->CNG_Codec_inst = (CNG_dec_inst *)savedPtr1;
240#endif
241 inst->pw16_readAddress = (WebRtc_Word16 *) savedPtr2;
242 inst->pw16_writeAddress = (WebRtc_Word16 *) savedPtr3;
243 inst->main_inst = savedPtr4;
244#ifdef NETEQ_VAD
245 inst->VADInst.VADState = savedVADptr;
246 inst->VADInst.initFunction = savedVADinit;
247 inst->VADInst.setmodeFunction = savedVADsetmode;
248 inst->VADInst.VADFunction = savedVADfunc;
249 inst->VADInst.VADEnabled = savedVADEnabled;
250 inst->VADInst.VADMode = savedVADMode;
251#endif /* NETEQ_VAD */
252
253 /* Initialize main part */
254 inst->fs = fs;
255 inst->millisecondsPerCall = saveMsPerCall;
256 inst->timestampsPerCall = inst->millisecondsPerCall * 8 * fs_mult;
257 inst->ExpandInst.w16_overlap = 5 * fs_mult;
258 inst->endPosition = 565 * fs_mult;
259 inst->curPosition = inst->endPosition - inst->ExpandInst.w16_overlap;
260 inst->w16_seedInc = 1;
261 inst->uw16_seed = 777;
262 inst->w16_muteFactor = 16384; /* 1.0 in Q14 */
263 inst->w16_frameLen = 3 * inst->timestampsPerCall; /* Dummy initialize to 30ms */
264
265 inst->w16_speechHistoryLen = 256 * fs_mult;
266 inst->pw16_speechHistory = &inst->speechBuffer[inst->endPosition
267 - inst->w16_speechHistoryLen];
268 inst->ExpandInst.pw16_overlapVec = &(inst->pw16_speechHistory[inst->w16_speechHistoryLen
269 - inst->ExpandInst.w16_overlap]);
270
271 /* Reusage of memory in speechBuffer inside Expand */
272 inst->ExpandInst.pw16_expVecs[0] = &inst->speechBuffer[0];
273 inst->ExpandInst.pw16_expVecs[1] = &inst->speechBuffer[126 * fs_mult];
274 inst->ExpandInst.pw16_arState = &inst->speechBuffer[2 * 126 * fs_mult];
275 inst->ExpandInst.pw16_arFilter = &inst->speechBuffer[2 * 126 * fs_mult
276 + UNVOICED_LPC_ORDER];
277 /* Ends at 2*126*fs_mult+UNVOICED_LPC_ORDER+(UNVOICED_LPC_ORDER+1) */
278
279 inst->ExpandInst.w16_expandMuteFactor = 16384; /* 1.0 in Q14 */
280
281 /* Initialize BGN part */
282 inst->BGNInst.pw16_filter[0] = 4096;
283 inst->BGNInst.w16_scale = 20000;
284 inst->BGNInst.w16_scaleShift = 24;
285 inst->BGNInst.w32_energyUpdate = 500000;
286 inst->BGNInst.w32_energyUpdateLow = 0;
287 inst->BGNInst.w32_energy = 2500;
288 inst->BGNInst.w16_initialized = 0;
289 inst->BGNInst.bgnMode = saveBgnMode;
290
291 /* Recreate statistics counters */WEBRTC_SPL_MEMCPY_W16(&(inst->statInst), &saveStats,
292 sizeof(DSPStats_t)/sizeof(WebRtc_Word16));
293
294#ifdef NETEQ_STEREO
295 /* Recreate MSinfo */WEBRTC_SPL_MEMCPY_W16(&(inst->msInfo), &saveMSinfo,
296 sizeof(MasterSlaveInfo)/sizeof(WebRtc_Word16));
297#endif
298
299#ifdef NETEQ_CNG_CODEC
300 if (inst->CNG_Codec_inst!=NULL)
301 {
302 /* initialize comfort noise generator */
303 res |= WebRtcCng_InitDec(inst->CNG_Codec_inst);
304 }
305#endif
306
307#ifdef NETEQ_VAD
308 /* initialize PostDecode VAD instance
309 (don't bother checking for NULL instance, this is done inside init function) */
310 res |= WebRtcNetEQ_InitVAD(&inst->VADInst, fs);
311#endif /* NETEQ_VAD */
312
313 return (res);
314}
315
316/****************************************************************************
317 * WebRtcNetEQ_AddressInit(...)
318 *
319 * Initializes the shared-memory communication on the DSP side.
320 *
321 * Input:
322 * - inst : NetEQ DSP instance
323 * - data2McuAddress : Pointer to memory where DSP writes / MCU reads
324 * - data2DspAddress : Pointer to memory where MCU writes / DSP reads
325 * - mainInst : NetEQ main instance
326 *
327 * Output:
328 * - inst : Updated instance
329 *
330 * Return value : 0 - ok
331 */
332
333int WebRtcNetEQ_AddressInit(DSPInst_t *inst, const void *data2McuAddress,
334 const void *data2DspAddress, const void *mainInst)
335{
336
337 /* set shared-memory addresses in the DSP instance */
338 inst->pw16_readAddress = (WebRtc_Word16 *) data2DspAddress;
339 inst->pw16_writeAddress = (WebRtc_Word16 *) data2McuAddress;
340
341 /* set pointer to main NetEQ instance */
342 inst->main_inst = (void *) mainInst;
343
344 /* set output frame size to 10 ms = 80 samples in narrowband */
345 inst->millisecondsPerCall = 10;
346 inst->timestampsPerCall = 80;
347
348 return (0);
349
350}
351
352/****************************************************************************
353 * NETEQDSP_clearInCallStats(...)
354 *
355 * Reset in-call statistics variables on DSP side.
356 *
357 * Input:
358 * - inst : NetEQ DSP instance
359 *
360 * Output:
361 * - inst : Updated instance
362 *
363 * Return value : 0 - ok
364 */
365
366int WebRtcNetEQ_ClearInCallStats(DSPInst_t *inst)
367{
niklase@google.com470e71d2011-07-07 08:21:25 +0000368 /* Reset statistics counters */
369 inst->statInst.accelerateLength = 0;
370 inst->statInst.expandLength = 0;
371 inst->statInst.preemptiveLength = 0;
roosa@google.comb8ba4d82012-12-14 00:06:18 +0000372 inst->statInst.addedSamples = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000373 return (0);
374}
375
376/****************************************************************************
377 * WebRtcNetEQ_ClearPostCallStats(...)
378 *
379 * Reset post-call statistics variables on DSP side.
380 *
381 * Input:
382 * - inst : NetEQ DSP instance
383 *
384 * Output:
385 * - inst : Updated instance
386 *
387 * Return value : 0 - ok
388 */
389
390int WebRtcNetEQ_ClearPostCallStats(DSPInst_t *inst)
391{
392
393 /* Reset statistics counters */
394 inst->statInst.expandedVoiceSamples = 0;
395 inst->statInst.expandedNoiseSamples = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000396 return (0);
397}
398
399#ifdef NETEQ_VAD
400
401/****************************************************************************
402 * WebRtcNetEQ_InitVAD(...)
403 *
404 * Initializes post-decode VAD instance.
405 *
406 * Input:
407 * - VADinst : PostDecodeVAD instance
408 * - fs : Initial sample rate
409 *
410 * Output:
411 * - VADinst : Updated instance
412 *
413 * Return value : 0 - Ok
414 * -1 - Error
415 */
416
417int WebRtcNetEQ_InitVAD(PostDecodeVAD_t *VADInst, WebRtc_UWord16 fs)
418{
419
420 int res = 0;
421
422 /* initially, disable the post-decode VAD */
423 VADInst->VADEnabled = 0;
424
425 if (VADInst->VADState != NULL /* if VAD state is provided */
426 && VADInst->initFunction != NULL /* and all function ... */
427 && VADInst->setmodeFunction != NULL /* ... pointers ... */
428 && VADInst->VADFunction != NULL) /* ... are defined */
429 {
bjornv@webrtc.orgab2bb822012-01-18 14:51:02 +0000430 res = VADInst->initFunction( VADInst->VADState ); /* call VAD init function */
niklase@google.com470e71d2011-07-07 08:21:25 +0000431 res |= WebRtcNetEQ_SetVADModeInternal( VADInst, VADInst->VADMode );
432
433 if (res!=0)
434 {
435 /* something is wrong; play it safe and set the VADstate to NULL */
436 VADInst->VADState = NULL;
437 }
438 else if (fs<=16000)
439 {
440 /* enable VAD if NB or WB (VAD cannot handle SWB) */
441 VADInst->VADEnabled = 1;
442 }
443 }
444
445 /* reset SID/CNG interval counter */
446 VADInst->SIDintervalCounter = 0;
447
448 /* initialize with active-speaker decision */
449 VADInst->VADDecision = 1;
450
451 return(res);
452
453}
454
455/****************************************************************************
456 * WebRtcNetEQ_SetVADModeInternal(...)
457 *
458 * Set the VAD mode in the VAD struct, and communicate it to the VAD instance
459 * if it exists.
460 *
461 * Input:
462 * - VADinst : PostDecodeVAD instance
463 * - mode : Mode number passed on to the VAD function
464 *
465 * Output:
466 * - VADinst : Updated instance
467 *
468 * Return value : 0 - Ok
469 * -1 - Error
470 */
471
bjornv@webrtc.orgf4b77fd2012-01-25 12:40:00 +0000472int WebRtcNetEQ_SetVADModeInternal(PostDecodeVAD_t *VADInst, int mode)
niklase@google.com470e71d2011-07-07 08:21:25 +0000473{
474
475 int res = 0;
476
477 VADInst->VADMode = mode;
478
479 if (VADInst->VADState != NULL)
480 {
481 /* call setmode function */
bjornv@webrtc.org152c34c2012-01-23 12:36:46 +0000482 res = VADInst->setmodeFunction(VADInst->VADState, mode);
niklase@google.com470e71d2011-07-07 08:21:25 +0000483 }
484
485 return(res);
486
487}
488
489#endif /* NETEQ_VAD */
490
491/****************************************************************************
492 * WebRtcNetEQ_FlushSpeechBuffer(...)
493 *
494 * Flush the speech buffer.
495 *
496 * Input:
497 * - inst : NetEq DSP instance
498 *
499 * Output:
500 * - inst : Updated instance
501 *
502 * Return value : 0 - ok
503 * : non-zero - error
504 */
505
506int WebRtcNetEQ_FlushSpeechBuffer(DSPInst_t *inst)
507{
508 WebRtc_Word16 fs_mult;
509
510 /* calcualte fs/8000 */
511 fs_mult = WebRtcSpl_DivW32W16ResW16(inst->fs, 8000);
512
513 /* clear buffer */
514 WebRtcSpl_MemSetW16(inst->speechBuffer, 0, SPEECH_BUF_SIZE);
515 inst->endPosition = 565 * fs_mult;
516 inst->curPosition = inst->endPosition - inst->ExpandInst.w16_overlap;
517
518 return 0;
519}
520