blob: ea2fa87d501f615bdea26cbd29ff261e52b4e1a2 [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} */
pbos@webrtc.org0946a562013-04-09 00:28:06 +000027const int16_t WebRtcNetEQ_kDownsample8kHzTbl[] = { 1229, 1638, 1229 };
niklase@google.com470e71d2011-07-07 08:21:25 +000028
29#ifdef NETEQ_WIDEBAND
30/* {0.15, 0.2, 0.3, 0.2, 0.15} */
pbos@webrtc.org0946a562013-04-09 00:28:06 +000031const int16_t WebRtcNetEQ_kDownsample16kHzTbl[] =
niklase@google.com470e71d2011-07-07 08:21:25 +000032{ 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} */
pbos@webrtc.org0946a562013-04-09 00:28:06 +000037const int16_t WebRtcNetEQ_kDownsample32kHzTbl[] =
niklase@google.com470e71d2011-07-07 08:21:25 +000038{ 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} */
pbos@webrtc.org0946a562013-04-09 00:28:06 +000043const int16_t WebRtcNetEQ_kDownsample48kHzTbl[] =
niklase@google.com470e71d2011-07-07 08:21:25 +000044{ 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 */
pbos@webrtc.org0946a562013-04-09 00:28:06 +000050const int16_t WebRtcNetEQ_kMixFractionFuncTbl[4] = { -5179, 19931, -16422, 5776 };
niklase@google.com470e71d2011-07-07 08:21:25 +000051
52/* Tabulated divisions to save complexity */
53/* 1049/{0, .., 6} */
pbos@webrtc.org0946a562013-04-09 00:28:06 +000054const int16_t WebRtcNetEQ_k1049div[7] = { 0, 1049, 524, 349, 262, 209, 174 };
niklase@google.com470e71d2011-07-07 08:21:25 +000055
56/* 2097/{0, .., 6} */
pbos@webrtc.org0946a562013-04-09 00:28:06 +000057const int16_t WebRtcNetEQ_k2097div[7] = { 0, 2097, 1048, 699, 524, 419, 349 };
niklase@google.com470e71d2011-07-07 08:21:25 +000058
59/* 5243/{0, .., 6} */
pbos@webrtc.org0946a562013-04-09 00:28:06 +000060const int16_t WebRtcNetEQ_k5243div[7] = { 0, 5243, 2621, 1747, 1310, 1048, 873 };
niklase@google.com470e71d2011-07-07 08:21:25 +000061
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
pbos@webrtc.org0946a562013-04-09 00:28:06 +000092void WebRtcNetEQ_40BitAccCrossCorr(int32_t *crossCorr,
93 int16_t *seq1,
94 int16_t *seq2,
95 int16_t dimSeq,
96 int16_t dimCrossCorr,
97 int16_t rShift,
98 int16_t step_seq2)
niklase@google.com470e71d2011-07-07 08:21:25 +000099{
100 int i, j;
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000101 int16_t *seq1Ptr, *seq2Ptr;
102 int64_t acc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000103
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
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000120 (*crossCorr) = (int32_t) (acc >> rShift);
niklase@google.com470e71d2011-07-07 08:21:25 +0000121 crossCorr++;
122 }
123}
124
125/****************************************************************************
126 * WebRtcNetEQ_40BitAccDotW16W16(...)
127 *
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000128 * Calculates the dot product between two vectors (int16_t)
niklase@google.com470e71d2011-07-07 08:21:25 +0000129 *
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
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000140int32_t WebRtcNetEQ_40BitAccDotW16W16(int16_t *vector1,
141 int16_t *vector2,
niklase@google.com470e71d2011-07-07 08:21:25 +0000142 int len,
143 int scaling)
144{
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000145 int32_t sum;
niklase@google.com470e71d2011-07-07 08:21:25 +0000146 int i;
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000147 int64_t acc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000148
149 acc = 0;
150 for (i = 0; i < len; i++)
151 {
152 acc += WEBRTC_SPL_MUL_16_16(*vector1++, *vector2++);
153 }
154
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000155 sum = (int32_t) (acc >> scaling);
niklase@google.com470e71d2011-07-07 08:21:25 +0000156
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
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000178int WebRtcNetEQ_DSPInit(DSPInst_t *inst, uint16_t fs)
niklase@google.com470e71d2011-07-07 08:21:25 +0000179{
180
181 int res = 0;
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000182 int16_t fs_mult;
niklase@google.com470e71d2011-07-07 08:21:25 +0000183
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;
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000196 int16_t 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;
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000200 int16_t saveMsPerCall = inst->millisecondsPerCall;
niklase@google.com470e71d2011-07-07 08:21:25 +0000201 enum BGNMode saveBgnMode = inst->BGNInst.bgnMode;
202#ifdef NETEQ_STEREO
turaj@webrtc.org3942f3a2013-06-04 21:31:22 +0000203 MasterSlaveInfo* saveMSinfo = inst->msInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000204#endif
205
206 /* copy contents of statInst to avoid clearing */WEBRTC_SPL_MEMCPY_W16(&saveStats, &(inst->statInst),
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000207 sizeof(DSPStats_t)/sizeof(int16_t));
niklase@google.com470e71d2011-07-07 08:21:25 +0000208
niklase@google.com470e71d2011-07-07 08:21:25 +0000209 /* check that the sample rate is valid */
210 if ((fs != 8000)
211#ifdef NETEQ_WIDEBAND
212 &&(fs!=16000)
213#endif
214#ifdef NETEQ_32KHZ_WIDEBAND
215 &&(fs!=32000)
216#endif
217#ifdef NETEQ_48KHZ_WIDEBAND
218 &&(fs!=48000)
219#endif
220 )
221 {
222 /* invalid rate */
223 return (CODEC_DB_UNSUPPORTED_FS);
224 }
225
226 /* calcualte fs/8000 */
227 fs_mult = WebRtcSpl_DivW32W16ResW16(fs, 8000);
228
229 /* Set everything to zero since most variables should be zero at start */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000230 WebRtcSpl_MemSetW16((int16_t *) inst, 0, sizeof(DSPInst_t) / sizeof(int16_t));
niklase@google.com470e71d2011-07-07 08:21:25 +0000231
232 /* Restore saved pointers */
233#ifdef NETEQ_CNG_CODEC
234 inst->CNG_Codec_inst = (CNG_dec_inst *)savedPtr1;
235#endif
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000236 inst->pw16_readAddress = (int16_t *) savedPtr2;
237 inst->pw16_writeAddress = (int16_t *) savedPtr3;
niklase@google.com470e71d2011-07-07 08:21:25 +0000238 inst->main_inst = savedPtr4;
239#ifdef NETEQ_VAD
240 inst->VADInst.VADState = savedVADptr;
241 inst->VADInst.initFunction = savedVADinit;
242 inst->VADInst.setmodeFunction = savedVADsetmode;
243 inst->VADInst.VADFunction = savedVADfunc;
244 inst->VADInst.VADEnabled = savedVADEnabled;
245 inst->VADInst.VADMode = savedVADMode;
246#endif /* NETEQ_VAD */
247
248 /* Initialize main part */
249 inst->fs = fs;
250 inst->millisecondsPerCall = saveMsPerCall;
251 inst->timestampsPerCall = inst->millisecondsPerCall * 8 * fs_mult;
252 inst->ExpandInst.w16_overlap = 5 * fs_mult;
253 inst->endPosition = 565 * fs_mult;
254 inst->curPosition = inst->endPosition - inst->ExpandInst.w16_overlap;
255 inst->w16_seedInc = 1;
256 inst->uw16_seed = 777;
257 inst->w16_muteFactor = 16384; /* 1.0 in Q14 */
258 inst->w16_frameLen = 3 * inst->timestampsPerCall; /* Dummy initialize to 30ms */
259
260 inst->w16_speechHistoryLen = 256 * fs_mult;
261 inst->pw16_speechHistory = &inst->speechBuffer[inst->endPosition
262 - inst->w16_speechHistoryLen];
263 inst->ExpandInst.pw16_overlapVec = &(inst->pw16_speechHistory[inst->w16_speechHistoryLen
264 - inst->ExpandInst.w16_overlap]);
265
266 /* Reusage of memory in speechBuffer inside Expand */
267 inst->ExpandInst.pw16_expVecs[0] = &inst->speechBuffer[0];
268 inst->ExpandInst.pw16_expVecs[1] = &inst->speechBuffer[126 * fs_mult];
269 inst->ExpandInst.pw16_arState = &inst->speechBuffer[2 * 126 * fs_mult];
270 inst->ExpandInst.pw16_arFilter = &inst->speechBuffer[2 * 126 * fs_mult
271 + UNVOICED_LPC_ORDER];
272 /* Ends at 2*126*fs_mult+UNVOICED_LPC_ORDER+(UNVOICED_LPC_ORDER+1) */
273
274 inst->ExpandInst.w16_expandMuteFactor = 16384; /* 1.0 in Q14 */
275
276 /* Initialize BGN part */
277 inst->BGNInst.pw16_filter[0] = 4096;
278 inst->BGNInst.w16_scale = 20000;
279 inst->BGNInst.w16_scaleShift = 24;
280 inst->BGNInst.w32_energyUpdate = 500000;
281 inst->BGNInst.w32_energyUpdateLow = 0;
282 inst->BGNInst.w32_energy = 2500;
283 inst->BGNInst.w16_initialized = 0;
284 inst->BGNInst.bgnMode = saveBgnMode;
285
286 /* Recreate statistics counters */WEBRTC_SPL_MEMCPY_W16(&(inst->statInst), &saveStats,
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000287 sizeof(DSPStats_t)/sizeof(int16_t));
niklase@google.com470e71d2011-07-07 08:21:25 +0000288
289#ifdef NETEQ_STEREO
turaj@webrtc.org3942f3a2013-06-04 21:31:22 +0000290 /* Write back the pointer. */
291 inst->msInfo = saveMSinfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000292#endif
293
294#ifdef NETEQ_CNG_CODEC
295 if (inst->CNG_Codec_inst!=NULL)
296 {
297 /* initialize comfort noise generator */
298 res |= WebRtcCng_InitDec(inst->CNG_Codec_inst);
299 }
300#endif
301
302#ifdef NETEQ_VAD
303 /* initialize PostDecode VAD instance
304 (don't bother checking for NULL instance, this is done inside init function) */
305 res |= WebRtcNetEQ_InitVAD(&inst->VADInst, fs);
306#endif /* NETEQ_VAD */
307
308 return (res);
309}
310
311/****************************************************************************
312 * WebRtcNetEQ_AddressInit(...)
313 *
314 * Initializes the shared-memory communication on the DSP side.
315 *
316 * Input:
317 * - inst : NetEQ DSP instance
318 * - data2McuAddress : Pointer to memory where DSP writes / MCU reads
319 * - data2DspAddress : Pointer to memory where MCU writes / DSP reads
320 * - mainInst : NetEQ main instance
321 *
322 * Output:
323 * - inst : Updated instance
324 *
325 * Return value : 0 - ok
326 */
327
328int WebRtcNetEQ_AddressInit(DSPInst_t *inst, const void *data2McuAddress,
329 const void *data2DspAddress, const void *mainInst)
330{
331
332 /* set shared-memory addresses in the DSP instance */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000333 inst->pw16_readAddress = (int16_t *) data2DspAddress;
334 inst->pw16_writeAddress = (int16_t *) data2McuAddress;
niklase@google.com470e71d2011-07-07 08:21:25 +0000335
336 /* set pointer to main NetEQ instance */
337 inst->main_inst = (void *) mainInst;
338
339 /* set output frame size to 10 ms = 80 samples in narrowband */
340 inst->millisecondsPerCall = 10;
341 inst->timestampsPerCall = 80;
342
343 return (0);
344
345}
346
347/****************************************************************************
348 * NETEQDSP_clearInCallStats(...)
349 *
350 * Reset in-call statistics variables on DSP side.
351 *
352 * Input:
353 * - inst : NetEQ DSP instance
354 *
355 * Output:
356 * - inst : Updated instance
357 *
358 * Return value : 0 - ok
359 */
360
361int WebRtcNetEQ_ClearInCallStats(DSPInst_t *inst)
362{
niklase@google.com470e71d2011-07-07 08:21:25 +0000363 /* Reset statistics counters */
364 inst->statInst.accelerateLength = 0;
365 inst->statInst.expandLength = 0;
366 inst->statInst.preemptiveLength = 0;
roosa@google.comb8ba4d82012-12-14 00:06:18 +0000367 inst->statInst.addedSamples = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000368 return (0);
369}
370
371/****************************************************************************
372 * WebRtcNetEQ_ClearPostCallStats(...)
373 *
374 * Reset post-call statistics variables on DSP side.
375 *
376 * Input:
377 * - inst : NetEQ DSP instance
378 *
379 * Output:
380 * - inst : Updated instance
381 *
382 * Return value : 0 - ok
383 */
384
385int WebRtcNetEQ_ClearPostCallStats(DSPInst_t *inst)
386{
387
388 /* Reset statistics counters */
389 inst->statInst.expandedVoiceSamples = 0;
390 inst->statInst.expandedNoiseSamples = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000391 return (0);
392}
393
turaj@webrtc.org92d1f072013-04-15 16:52:04 +0000394/****************************************************************************
395 * WebRtcNetEQ_ClearActivityStats(...)
396 *
397 * Reset processing activity statistics.
398 *
399 * Input:
400 * - inst : NetEQ DSP instance
401 *
402 * Output:
403 * - inst : Updated instance
404 *
405 */
406
407void WebRtcNetEQ_ClearActivityStats(DSPInst_t *inst) {
408 memset(&inst->activity_stats, 0, sizeof(ActivityStats));
409}
410
niklase@google.com470e71d2011-07-07 08:21:25 +0000411#ifdef NETEQ_VAD
412
413/****************************************************************************
414 * WebRtcNetEQ_InitVAD(...)
415 *
416 * Initializes post-decode VAD instance.
417 *
418 * Input:
419 * - VADinst : PostDecodeVAD instance
420 * - fs : Initial sample rate
421 *
422 * Output:
423 * - VADinst : Updated instance
424 *
425 * Return value : 0 - Ok
426 * -1 - Error
427 */
428
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000429int WebRtcNetEQ_InitVAD(PostDecodeVAD_t *VADInst, uint16_t fs)
niklase@google.com470e71d2011-07-07 08:21:25 +0000430{
431
432 int res = 0;
433
434 /* initially, disable the post-decode VAD */
435 VADInst->VADEnabled = 0;
436
437 if (VADInst->VADState != NULL /* if VAD state is provided */
438 && VADInst->initFunction != NULL /* and all function ... */
439 && VADInst->setmodeFunction != NULL /* ... pointers ... */
440 && VADInst->VADFunction != NULL) /* ... are defined */
441 {
bjornv@webrtc.orgab2bb822012-01-18 14:51:02 +0000442 res = VADInst->initFunction( VADInst->VADState ); /* call VAD init function */
niklase@google.com470e71d2011-07-07 08:21:25 +0000443 res |= WebRtcNetEQ_SetVADModeInternal( VADInst, VADInst->VADMode );
444
445 if (res!=0)
446 {
447 /* something is wrong; play it safe and set the VADstate to NULL */
448 VADInst->VADState = NULL;
449 }
450 else if (fs<=16000)
451 {
452 /* enable VAD if NB or WB (VAD cannot handle SWB) */
453 VADInst->VADEnabled = 1;
454 }
455 }
456
457 /* reset SID/CNG interval counter */
458 VADInst->SIDintervalCounter = 0;
459
460 /* initialize with active-speaker decision */
461 VADInst->VADDecision = 1;
462
463 return(res);
464
465}
466
467/****************************************************************************
468 * WebRtcNetEQ_SetVADModeInternal(...)
469 *
470 * Set the VAD mode in the VAD struct, and communicate it to the VAD instance
471 * if it exists.
472 *
473 * Input:
474 * - VADinst : PostDecodeVAD instance
475 * - mode : Mode number passed on to the VAD function
476 *
477 * Output:
478 * - VADinst : Updated instance
479 *
480 * Return value : 0 - Ok
481 * -1 - Error
482 */
483
bjornv@webrtc.orgf4b77fd2012-01-25 12:40:00 +0000484int WebRtcNetEQ_SetVADModeInternal(PostDecodeVAD_t *VADInst, int mode)
niklase@google.com470e71d2011-07-07 08:21:25 +0000485{
486
487 int res = 0;
488
489 VADInst->VADMode = mode;
490
491 if (VADInst->VADState != NULL)
492 {
493 /* call setmode function */
bjornv@webrtc.org152c34c2012-01-23 12:36:46 +0000494 res = VADInst->setmodeFunction(VADInst->VADState, mode);
niklase@google.com470e71d2011-07-07 08:21:25 +0000495 }
496
497 return(res);
498
499}
500
501#endif /* NETEQ_VAD */
502
503/****************************************************************************
504 * WebRtcNetEQ_FlushSpeechBuffer(...)
505 *
506 * Flush the speech buffer.
507 *
508 * Input:
509 * - inst : NetEq DSP instance
510 *
511 * Output:
512 * - inst : Updated instance
513 *
514 * Return value : 0 - ok
515 * : non-zero - error
516 */
517
518int WebRtcNetEQ_FlushSpeechBuffer(DSPInst_t *inst)
519{
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000520 int16_t fs_mult;
niklase@google.com470e71d2011-07-07 08:21:25 +0000521
522 /* calcualte fs/8000 */
523 fs_mult = WebRtcSpl_DivW32W16ResW16(inst->fs, 8000);
524
525 /* clear buffer */
526 WebRtcSpl_MemSetW16(inst->speechBuffer, 0, SPEECH_BUF_SIZE);
527 inst->endPosition = 565 * fs_mult;
528 inst->curPosition = inst->endPosition - inst->ExpandInst.w16_overlap;
529
530 return 0;
531}
532