blob: 8f62007310ca31661938e516549cd68a7c0cc7e5 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
andrew@webrtc.org4e423b32012-04-23 18:59:00 +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 * Implementation of RecOut function, which is the main function for the audio output
13 * process. This function must be called (through the NetEQ API) once every 10 ms.
14 */
15
16#include "dsp.h"
17
18#include <assert.h>
19#include <string.h> /* to define NULL */
20
21#include "signal_processing_library.h"
22
23#include "dsp_helpfunctions.h"
24#include "neteq_error_codes.h"
25#include "neteq_defines.h"
26#include "mcu_dsp_common.h"
27
28/* Audio types */
29#define TYPE_SPEECH 1
30#define TYPE_CNG 2
31
32#ifdef NETEQ_DELAY_LOGGING
33#include "delay_logging.h"
34#include <stdio.h>
35#pragma message("*******************************************************************")
36#pragma message("You have specified to use NETEQ_DELAY_LOGGING in the NetEQ library.")
37#pragma message("Make sure that your test application supports this.")
38#pragma message("*******************************************************************")
39#endif
40
41/* Scratch usage:
42
43 Type Name size startpos endpos
pbos@webrtc.org0946a562013-04-09 00:28:06 +000044 int16_t pw16_NetEqAlgorithm_buffer 1080*fs/8000 0 1080*fs/8000-1
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +000045 struct dspInfo 6 1080*fs/8000 1085*fs/8000
niklase@google.com470e71d2011-07-07 08:21:25 +000046
47 func WebRtcNetEQ_Normal 40+495*fs/8000 0 39+495*fs/8000
48 func WebRtcNetEQ_Merge 40+496*fs/8000 0 39+496*fs/8000
49 func WebRtcNetEQ_Expand 40+370*fs/8000 126*fs/800 39+496*fs/8000
50 func WebRtcNetEQ_Accelerate 210 240*fs/8000 209+240*fs/8000
51 func WebRtcNetEQ_BGNUpdate 69 480*fs/8000 68+480*fs/8000
52
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +000053 Total: 1086*fs/8000
niklase@google.com470e71d2011-07-07 08:21:25 +000054 */
55
56#define SCRATCH_ALGORITHM_BUFFER 0
57#define SCRATCH_NETEQ_NORMAL 0
58#define SCRATCH_NETEQ_MERGE 0
59
60#if (defined(NETEQ_48KHZ_WIDEBAND))
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +000061#define SCRATCH_DSP_INFO 6480
niklase@google.com470e71d2011-07-07 08:21:25 +000062#define SCRATCH_NETEQ_ACCELERATE 1440
63#define SCRATCH_NETEQ_BGN_UPDATE 2880
64#define SCRATCH_NETEQ_EXPAND 756
65#elif (defined(NETEQ_32KHZ_WIDEBAND))
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +000066#define SCRATCH_DSP_INFO 4320
niklase@google.com470e71d2011-07-07 08:21:25 +000067#define SCRATCH_NETEQ_ACCELERATE 960
68#define SCRATCH_NETEQ_BGN_UPDATE 1920
69#define SCRATCH_NETEQ_EXPAND 504
70#elif (defined(NETEQ_WIDEBAND))
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +000071#define SCRATCH_DSP_INFO 2160
niklase@google.com470e71d2011-07-07 08:21:25 +000072#define SCRATCH_NETEQ_ACCELERATE 480
73#define SCRATCH_NETEQ_BGN_UPDATE 960
74#define SCRATCH_NETEQ_EXPAND 252
75#else /* NB */
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +000076#define SCRATCH_DSP_INFO 1080
niklase@google.com470e71d2011-07-07 08:21:25 +000077#define SCRATCH_NETEQ_ACCELERATE 240
78#define SCRATCH_NETEQ_BGN_UPDATE 480
79#define SCRATCH_NETEQ_EXPAND 126
80#endif
81
82#if (defined(NETEQ_48KHZ_WIDEBAND))
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +000083#define SIZE_SCRATCH_BUFFER 6516
niklase@google.com470e71d2011-07-07 08:21:25 +000084#elif (defined(NETEQ_32KHZ_WIDEBAND))
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +000085#define SIZE_SCRATCH_BUFFER 4344
niklase@google.com470e71d2011-07-07 08:21:25 +000086#elif (defined(NETEQ_WIDEBAND))
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +000087#define SIZE_SCRATCH_BUFFER 2172
niklase@google.com470e71d2011-07-07 08:21:25 +000088#else /* NB */
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +000089#define SIZE_SCRATCH_BUFFER 1086
niklase@google.com470e71d2011-07-07 08:21:25 +000090#endif
91
92#ifdef NETEQ_DELAY_LOGGING
93extern FILE *delay_fid2; /* file pointer to delay log file */
pbos@webrtc.org0946a562013-04-09 00:28:06 +000094extern uint32_t tot_received_packets;
niklase@google.com470e71d2011-07-07 08:21:25 +000095#endif
96
97
pbos@webrtc.org0946a562013-04-09 00:28:06 +000098int WebRtcNetEQ_RecOutInternal(DSPInst_t *inst, int16_t *pw16_outData,
turaj@webrtc.org28d54ab2013-04-22 18:53:35 +000099 int16_t *pw16_len, int16_t BGNonly,
100 int av_sync)
niklase@google.com470e71d2011-07-07 08:21:25 +0000101{
102
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000103 int16_t blockLen, payloadLen, len = 0, pos;
104 int16_t w16_tmp1, w16_tmp2, w16_tmp3, DataEnough;
105 int16_t *blockPtr;
106 int16_t MD = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000107
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000108 int16_t speechType = TYPE_SPEECH;
109 uint16_t instr;
110 uint16_t uw16_tmp;
niklase@google.com470e71d2011-07-07 08:21:25 +0000111#ifdef SCRATCH
112 char pw8_ScratchBuffer[((SIZE_SCRATCH_BUFFER + 1) * 2)];
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000113 int16_t *pw16_scratchPtr = (int16_t*) pw8_ScratchBuffer;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000114 /* pad with 240*fs_mult to match the overflow guard below */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000115 int16_t pw16_decoded_buffer[NETEQ_MAX_FRAME_SIZE+240*6];
116 int16_t *pw16_NetEqAlgorithm_buffer = pw16_scratchPtr
niklase@google.com470e71d2011-07-07 08:21:25 +0000117 + SCRATCH_ALGORITHM_BUFFER;
118 DSP2MCU_info_t *dspInfo = (DSP2MCU_info_t*) (pw16_scratchPtr + SCRATCH_DSP_INFO);
119#else
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000120 /* pad with 240*fs_mult to match the overflow guard below */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000121 int16_t pw16_decoded_buffer[NETEQ_MAX_FRAME_SIZE+240*6];
122 int16_t pw16_NetEqAlgorithm_buffer[NETEQ_MAX_OUTPUT_SIZE+240*6];
niklase@google.com470e71d2011-07-07 08:21:25 +0000123 DSP2MCU_info_t dspInfoStruct;
124 DSP2MCU_info_t *dspInfo = &dspInfoStruct;
125#endif
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000126 int16_t fs_mult;
niklase@google.com470e71d2011-07-07 08:21:25 +0000127 int borrowedSamples;
128 int oldBorrowedSamples;
129 int return_value = 0;
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000130 int16_t lastModeBGNonly = (inst->w16_mode & MODE_BGN_ONLY) != 0; /* check BGN flag */
niklase@google.com470e71d2011-07-07 08:21:25 +0000131 void *mainInstBackup = inst->main_inst;
132
133#ifdef NETEQ_DELAY_LOGGING
henrik.lundin@webrtc.orgd7989532012-01-20 13:42:16 +0000134 int temp_var;
niklase@google.com470e71d2011-07-07 08:21:25 +0000135#endif
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000136 int16_t dtmfValue = -1;
137 int16_t dtmfVolume = -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000138 int playDtmf = 0;
henrik.lundin@webrtc.org44ef3772011-12-07 10:43:25 +0000139#ifdef NETEQ_ATEVENT_DECODE
niklase@google.com470e71d2011-07-07 08:21:25 +0000140 int dtmfSwitch = 0;
henrik.lundin@webrtc.org44ef3772011-12-07 10:43:25 +0000141#endif
niklase@google.com470e71d2011-07-07 08:21:25 +0000142#ifdef NETEQ_STEREO
143 MasterSlaveInfo *msInfo = inst->msInfo;
144#endif
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000145 int16_t *sharedMem = pw16_NetEqAlgorithm_buffer; /* Reuse memory SHARED_MEM_SIZE size */
niklase@google.com470e71d2011-07-07 08:21:25 +0000146 inst->pw16_readAddress = sharedMem;
147 inst->pw16_writeAddress = sharedMem;
148
149 /* Get information about if there is one descriptor left */
150 if (inst->codec_ptr_inst.funcGetMDinfo != NULL)
151 {
152 MD = inst->codec_ptr_inst.funcGetMDinfo(inst->codec_ptr_inst.codec_state);
153 if (MD > 0)
154 MD = 1;
155 else
156 MD = 0;
157 }
158
159#ifdef NETEQ_STEREO
160 if ((msInfo->msMode == NETEQ_SLAVE) && (inst->codec_ptr_inst.funcDecode != NULL))
161 {
162 /*
163 * Valid function pointers indicate that we have decoded something,
164 * and that the timestamp information is correct.
165 */
166
167 /* Get the information from master to correct synchronization */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000168 uint32_t currentMasterTimestamp;
169 uint32_t currentSlaveTimestamp;
niklase@google.com470e71d2011-07-07 08:21:25 +0000170
171 currentMasterTimestamp = msInfo->endTimestamp - msInfo->samplesLeftWithOverlap;
172 currentSlaveTimestamp = inst->endTimestamp - (inst->endPosition - inst->curPosition);
173
andrew@webrtc.org4e423b32012-04-23 18:59:00 +0000174 /* Partition the uint32_t space in three: [0 0.25) [0.25 0.75] (0.75 1]
175 * We consider a wrap to have occurred if the timestamps are in
176 * different edge partitions.
177 */
178 if (currentSlaveTimestamp < 0x40000000 &&
179 currentMasterTimestamp > 0xc0000000) {
180 // Slave has wrapped.
181 currentSlaveTimestamp += (0xffffffff - currentMasterTimestamp) + 1;
182 currentMasterTimestamp = 0;
183 } else if (currentMasterTimestamp < 0x40000000 &&
184 currentSlaveTimestamp > 0xc0000000) {
185 // Master has wrapped.
186 currentMasterTimestamp += (0xffffffff - currentSlaveTimestamp) + 1;
187 currentSlaveTimestamp = 0;
188 }
189
niklase@google.com470e71d2011-07-07 08:21:25 +0000190 if (currentSlaveTimestamp < currentMasterTimestamp)
191 {
192 /* brute-force discard a number of samples to catch up */
193 inst->curPosition += currentMasterTimestamp - currentSlaveTimestamp;
194
niklase@google.com470e71d2011-07-07 08:21:25 +0000195 }
196 else if (currentSlaveTimestamp > currentMasterTimestamp)
197 {
198 /* back off current position to slow down */
199 inst->curPosition -= currentSlaveTimestamp - currentMasterTimestamp;
niklase@google.com470e71d2011-07-07 08:21:25 +0000200 }
andrew@webrtc.org4e423b32012-04-23 18:59:00 +0000201
202 /* make sure we have at least "overlap" samples left */
203 inst->curPosition = WEBRTC_SPL_MIN(inst->curPosition,
204 inst->endPosition - inst->ExpandInst.w16_overlap);
205
206 /* make sure we do not end up outside the speech history */
207 inst->curPosition = WEBRTC_SPL_MAX(inst->curPosition, 0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000208 }
209#endif
210
211 /* Write status data to shared memory */
212 dspInfo->playedOutTS = inst->endTimestamp;
213 dspInfo->samplesLeft = inst->endPosition - inst->curPosition
214 - inst->ExpandInst.w16_overlap;
215 dspInfo->MD = MD;
216 dspInfo->lastMode = inst->w16_mode;
217 dspInfo->frameLen = inst->w16_frameLen;
218
219 /* Force update of codec if codec function is NULL */
220 if (inst->codec_ptr_inst.funcDecode == NULL)
221 {
222 dspInfo->lastMode |= MODE_AWAITING_CODEC_PTR;
223 }
224
225#ifdef NETEQ_STEREO
226 if (msInfo->msMode == NETEQ_SLAVE && (msInfo->extraInfo == DTMF_OVERDUB
227 || msInfo->extraInfo == DTMF_ONLY))
228 {
229 /* Signal that the master instance generated DTMF tones */
230 dspInfo->lastMode |= MODE_MASTER_DTMF_SIGNAL;
231 }
232
233 if (msInfo->msMode != NETEQ_MONO)
234 {
235 /* We are using stereo mode; signal this to MCU side */
236 dspInfo->lastMode |= MODE_USING_STEREO;
237 }
238#endif
239
240 WEBRTC_SPL_MEMCPY_W8(inst->pw16_writeAddress,dspInfo,sizeof(DSP2MCU_info_t));
241
242 /* Signal MCU with "interrupt" call to main inst*/
243#ifdef NETEQ_STEREO
244 assert(msInfo != NULL);
245 if (msInfo->msMode == NETEQ_MASTER)
246 {
247 /* clear info to slave */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000248 WebRtcSpl_MemSetW16((int16_t *) msInfo, 0,
249 sizeof(MasterSlaveInfo) / sizeof(int16_t));
niklase@google.com470e71d2011-07-07 08:21:25 +0000250 /* re-set mode */
251 msInfo->msMode = NETEQ_MASTER;
252
253 /* Store some information to slave */
254 msInfo->endTimestamp = inst->endTimestamp;
255 msInfo->samplesLeftWithOverlap = inst->endPosition - inst->curPosition;
256 }
257#endif
258
259 /*
260 * This call will trigger the MCU side to make a decision based on buffer contents and
261 * decision history. Instructions, encoded data and function pointers will be written
262 * to the shared memory.
263 */
264 return_value = WebRtcNetEQ_DSP2MCUinterrupt((MainInst_t *) inst->main_inst, sharedMem);
265
266 /* Read MCU data and instructions */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000267 instr = (uint16_t) (inst->pw16_readAddress[0] & 0xf000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000268
269#ifdef NETEQ_STEREO
270 if (msInfo->msMode == NETEQ_MASTER)
271 {
272 msInfo->instruction = instr;
273 }
274 else if (msInfo->msMode == NETEQ_SLAVE)
275 {
276 /* Nothing to do */
277 }
278#endif
279
280 /* check for error returned from MCU side, if so, return error */
281 if (return_value < 0)
282 {
283 inst->w16_mode = MODE_ERROR;
284 dspInfo->lastMode = MODE_ERROR;
285 return return_value;
286 }
287
288 blockPtr = &((inst->pw16_readAddress)[3]);
289
290 /* Check for DTMF payload flag */
291 if ((inst->pw16_readAddress[0] & DSP_DTMF_PAYLOAD) != 0)
292 {
293 playDtmf = 1;
294 dtmfValue = blockPtr[1];
295 dtmfVolume = blockPtr[2];
296 blockPtr += 3;
297
298#ifdef NETEQ_STEREO
299 if (msInfo->msMode == NETEQ_MASTER)
300 {
301 /* signal to slave that master is using DTMF */
302 msInfo->extraInfo = DTMF_OVERDUB;
303 }
304#endif
305 }
306
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000307 blockLen = (((*blockPtr) & DSP_CODEC_MASK_RED_FLAG) + 1) >> 1; /* In # of int16_t */
niklase@google.com470e71d2011-07-07 08:21:25 +0000308 payloadLen = ((*blockPtr) & DSP_CODEC_MASK_RED_FLAG);
309 blockPtr++;
310
311 /* Do we have to change our decoder? */
312 if ((inst->pw16_readAddress[0] & 0x0f00) == DSP_CODEC_NEW_CODEC)
313 {
314 WEBRTC_SPL_MEMCPY_W16(&inst->codec_ptr_inst,blockPtr,(payloadLen+1)>>1);
315 if (inst->codec_ptr_inst.codec_fs != 0)
316 {
317 return_value = WebRtcNetEQ_DSPInit(inst, inst->codec_ptr_inst.codec_fs);
318 if (return_value != 0)
319 { /* error returned */
320 instr = DSP_INSTR_FADE_TO_BGN; /* emergency instruction */
321 }
322#ifdef NETEQ_DELAY_LOGGING
323 temp_var = NETEQ_DELAY_LOGGING_SIGNAL_CHANGE_FS;
leozwang@webrtc.org354b0ed2012-06-01 17:46:21 +0000324 if ((fwrite(&temp_var, sizeof(int),
325 1, delay_fid2) != 1) ||
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000326 (fwrite(&inst->fs, sizeof(uint16_t),
leozwang@webrtc.org354b0ed2012-06-01 17:46:21 +0000327 1, delay_fid2) != 1)) {
328 return -1;
329 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000330#endif
331 }
332
333 /* Copy it again since the init destroys this part */
334
335 WEBRTC_SPL_MEMCPY_W16(&inst->codec_ptr_inst,blockPtr,(payloadLen+1)>>1);
336 inst->endTimestamp = inst->codec_ptr_inst.timeStamp;
337 inst->videoSyncTimestamp = inst->codec_ptr_inst.timeStamp;
338 blockPtr += blockLen;
339 blockLen = (((*blockPtr) & DSP_CODEC_MASK_RED_FLAG) + 1) >> 1;
340 payloadLen = ((*blockPtr) & DSP_CODEC_MASK_RED_FLAG);
341 blockPtr++;
342 if (inst->codec_ptr_inst.funcDecodeInit != NULL)
343 {
344 inst->codec_ptr_inst.funcDecodeInit(inst->codec_ptr_inst.codec_state);
345 }
346
347#ifdef NETEQ_CNG_CODEC
348
349 /* Also update the CNG state as this might be uninitialized */
350
351 WEBRTC_SPL_MEMCPY_W16(&inst->CNG_Codec_inst,blockPtr,(payloadLen+1)>>1);
352 blockPtr += blockLen;
353 blockLen = (((*blockPtr) & DSP_CODEC_MASK_RED_FLAG) + 1) >> 1;
354 payloadLen = ((*blockPtr) & DSP_CODEC_MASK_RED_FLAG);
355 blockPtr++;
356 if (inst->CNG_Codec_inst != NULL)
357 {
358 WebRtcCng_InitDec(inst->CNG_Codec_inst);
359 }
360#endif
361 }
362 else if ((inst->pw16_readAddress[0] & 0x0f00) == DSP_CODEC_RESET)
363 {
364 /* Reset the current codec (but not DSP struct) */
365 if (inst->codec_ptr_inst.funcDecodeInit != NULL)
366 {
367 inst->codec_ptr_inst.funcDecodeInit(inst->codec_ptr_inst.codec_state);
368 }
369
370#ifdef NETEQ_CNG_CODEC
371 /* And reset CNG */
372 if (inst->CNG_Codec_inst != NULL)
373 {
374 WebRtcCng_InitDec(inst->CNG_Codec_inst);
375 }
376#endif /*NETEQ_CNG_CODEC*/
377 }
378
379 fs_mult = WebRtcNetEQ_CalcFsMult(inst->fs);
380
381 /* Add late packet? */
382 if ((inst->pw16_readAddress[0] & 0x0f00) == DSP_CODEC_ADD_LATE_PKT)
383 {
384 if (inst->codec_ptr_inst.funcAddLatePkt != NULL)
385 {
386 /* Only do this if the codec has support for Add Late Pkt */
387 inst->codec_ptr_inst.funcAddLatePkt(inst->codec_ptr_inst.codec_state, blockPtr,
388 payloadLen);
389 }
390 blockPtr += blockLen;
391 blockLen = (((*blockPtr) & DSP_CODEC_MASK_RED_FLAG) + 1) >> 1; /* In # of Word16 */
392 payloadLen = ((*blockPtr) & DSP_CODEC_MASK_RED_FLAG);
393 blockPtr++;
394 }
395
396 /* Do we have to decode data? */
397 if ((instr == DSP_INSTR_NORMAL) || (instr == DSP_INSTR_ACCELERATE) || (instr
398 == DSP_INSTR_MERGE) || (instr == DSP_INSTR_PREEMPTIVE_EXPAND))
399 {
400 /* Do we need to update codec-internal PLC state? */
401 if ((instr == DSP_INSTR_MERGE) && (inst->codec_ptr_inst.funcDecodePLC != NULL))
402 {
403 len = 0;
404 len = inst->codec_ptr_inst.funcDecodePLC(inst->codec_ptr_inst.codec_state,
405 &pw16_decoded_buffer[len], 1);
406 }
407 len = 0;
408
409 /* Do decoding */
410 while ((blockLen > 0) && (len < (240 * fs_mult))) /* Guard somewhat against overflow */
411 {
412 if (inst->codec_ptr_inst.funcDecode != NULL)
413 {
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000414 int16_t dec_Len;
niklase@google.com470e71d2011-07-07 08:21:25 +0000415 if (!BGNonly)
416 {
turaj@webrtc.org28d54ab2013-04-22 18:53:35 +0000417 /* Check if this is a sync payload. */
418 if (av_sync && WebRtcNetEQ_IsSyncPayload(blockPtr,
419 payloadLen)) {
420 /* Zero-stuffing with same size as the last frame. */
421 dec_Len = inst->w16_frameLen;
422 memset(&pw16_decoded_buffer[len], 0, dec_Len *
423 sizeof(pw16_decoded_buffer[len]));
424 } else {
niklase@google.com470e71d2011-07-07 08:21:25 +0000425 /* Do decoding as normal
426 *
427 * blockPtr is pointing to payload, at this point,
turaj@webrtc.org28d54ab2013-04-22 18:53:35 +0000428 * the most significant bit of *(blockPtr - 1) is a flag if
429 * set to 1 indicates that the following payload is the
430 * redundant payload.
niklase@google.com470e71d2011-07-07 08:21:25 +0000431 */
432 if (((*(blockPtr - 1) & DSP_CODEC_RED_FLAG) != 0)
433 && (inst->codec_ptr_inst.funcDecodeRCU != NULL))
434 {
turaj@webrtc.org28d54ab2013-04-22 18:53:35 +0000435 dec_Len = inst->codec_ptr_inst.funcDecodeRCU(
436 inst->codec_ptr_inst.codec_state, blockPtr,
437 payloadLen, &pw16_decoded_buffer[len], &speechType);
niklase@google.com470e71d2011-07-07 08:21:25 +0000438 }
439 else
440 {
turaj@webrtc.org28d54ab2013-04-22 18:53:35 +0000441 /* Regular decoding. */
442 dec_Len = inst->codec_ptr_inst.funcDecode(
443 inst->codec_ptr_inst.codec_state, blockPtr,
444 payloadLen, &pw16_decoded_buffer[len], &speechType);
niklase@google.com470e71d2011-07-07 08:21:25 +0000445 }
turaj@webrtc.org28d54ab2013-04-22 18:53:35 +0000446 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000447 }
448 else
449 {
450 /*
451 * Background noise mode: don't decode, just produce the same length BGN.
452 * Don't call Expand for BGN here, since Expand uses the memory where the
453 * bitstreams are stored (sharemem).
454 */
455 dec_Len = inst->w16_frameLen;
456 }
457
458 if (dec_Len > 0)
459 {
460 len += dec_Len;
461 /* Update frameLen */
462 inst->w16_frameLen = dec_Len;
463 }
464 else if (dec_Len < 0)
465 {
466 /* Error */
467 len = -1;
468 break;
469 }
470 /*
471 * Sanity check (although we might still write outside memory when this
472 * happens...)
473 */
474 if (len > NETEQ_MAX_FRAME_SIZE)
475 {
476 WebRtcSpl_MemSetW16(pw16_outData, 0, inst->timestampsPerCall);
477 *pw16_len = inst->timestampsPerCall;
478 inst->w16_mode = MODE_ERROR;
479 dspInfo->lastMode = MODE_ERROR;
480 return RECOUT_ERROR_DECODED_TOO_MUCH;
481 }
482
483 /* Verify that instance was not corrupted by decoder */
484 if (mainInstBackup != inst->main_inst)
485 {
486 /* Instance is corrupt */
487 return CORRUPT_INSTANCE;
488 }
489
490 }
491 blockPtr += blockLen;
492 blockLen = (((*blockPtr) & DSP_CODEC_MASK_RED_FLAG) + 1) >> 1; /* In # of Word16 */
493 payloadLen = ((*blockPtr) & DSP_CODEC_MASK_RED_FLAG);
494 blockPtr++;
495 }
496
497 if (len < 0)
498 {
499 len = 0;
500 inst->endTimestamp += inst->w16_frameLen; /* advance one frame */
501 if (inst->codec_ptr_inst.funcGetErrorCode != NULL)
502 {
503 return_value = -inst->codec_ptr_inst.funcGetErrorCode(
504 inst->codec_ptr_inst.codec_state);
505 }
506 else
507 {
508 return_value = RECOUT_ERROR_DECODING;
509 }
510 instr = DSP_INSTR_FADE_TO_BGN;
511 }
512 if (speechType != TYPE_CNG)
513 {
514 /*
515 * Don't increment timestamp if codec returned CNG speech type
516 * since in this case, the MCU side will increment the CNGplayedTS counter.
517 */
518 inst->endTimestamp += len;
519 }
520 }
521 else if (instr == DSP_INSTR_NORMAL_ONE_DESC)
522 {
523 if (inst->codec_ptr_inst.funcDecode != NULL)
524 {
525 len = inst->codec_ptr_inst.funcDecode(inst->codec_ptr_inst.codec_state, NULL, 0,
526 pw16_decoded_buffer, &speechType);
527#ifdef NETEQ_DELAY_LOGGING
528 temp_var = NETEQ_DELAY_LOGGING_SIGNAL_DECODE_ONE_DESC;
leozwang@webrtc.org354b0ed2012-06-01 17:46:21 +0000529 if (fwrite(&temp_var, sizeof(int), 1, delay_fid2) != 1) {
530 return -1;
531 }
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000532 if (fwrite(&inst->endTimestamp, sizeof(uint32_t),
leozwang@webrtc.org354b0ed2012-06-01 17:46:21 +0000533 1, delay_fid2) != 1) {
534 return -1;
535 }
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000536 if (fwrite(&dspInfo->samplesLeft, sizeof(uint16_t),
leozwang@webrtc.org354b0ed2012-06-01 17:46:21 +0000537 1, delay_fid2) != 1) {
538 return -1;
539 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000540 tot_received_packets++;
541#endif
542 }
543 if (speechType != TYPE_CNG)
544 {
545 /*
546 * Don't increment timestamp if codec returned CNG speech type
547 * since in this case, the MCU side will increment the CNGplayedTS counter.
548 */
549 inst->endTimestamp += len;
550 }
551
552 /* Verify that instance was not corrupted by decoder */
553 if (mainInstBackup != inst->main_inst)
554 {
555 /* Instance is corrupt */
556 return CORRUPT_INSTANCE;
557 }
558
559 if (len <= 0)
560 {
561 len = 0;
562 if (inst->codec_ptr_inst.funcGetErrorCode != NULL)
563 {
564 return_value = -inst->codec_ptr_inst.funcGetErrorCode(
565 inst->codec_ptr_inst.codec_state);
566 }
567 else
568 {
569 return_value = RECOUT_ERROR_DECODING;
570 }
571 if ((inst->codec_ptr_inst.funcDecodeInit != NULL)
572 && (inst->codec_ptr_inst.codec_state != NULL))
573 {
574 /* Reinitialize codec state as something is obviously wrong */
575 inst->codec_ptr_inst.funcDecodeInit(inst->codec_ptr_inst.codec_state);
576 }
577 inst->endTimestamp += inst->w16_frameLen; /* advance one frame */
578 instr = DSP_INSTR_FADE_TO_BGN;
579 }
580 }
581
582 if (len == 0 && lastModeBGNonly) /* no new data */
583 {
584 BGNonly = 1; /* force BGN this time too */
585 }
586
587#ifdef NETEQ_VAD
588 if ((speechType == TYPE_CNG) /* decoder responded with codec-internal CNG */
589 || ((instr == DSP_INSTR_DO_RFC3389CNG) && (blockLen > 0)) /* ... or, SID frame */
590 || (inst->fs > 16000)) /* ... or, if not NB or WB */
591 {
592 /* disable post-decode VAD upon first sign of send-side DTX/VAD active, or if SWB */
593 inst->VADInst.VADEnabled = 0;
594 inst->VADInst.VADDecision = 1; /* set to always active, just to be on the safe side */
595 inst->VADInst.SIDintervalCounter = 0; /* reset SID interval counter */
596 }
597 else if (!inst->VADInst.VADEnabled) /* VAD disabled and no SID/CNG data observed this time */
598 {
599 inst->VADInst.SIDintervalCounter++; /* increase counter */
600 }
601
602 /* check for re-enabling the VAD */
603 if (inst->VADInst.SIDintervalCounter >= POST_DECODE_VAD_AUTO_ENABLE)
604 {
605 /*
606 * It's been a while since the last CNG/SID frame was observed => re-enable VAD.
607 * (Do not care to look for a VAD instance, since this is done inside the init
608 * function)
609 */
610 WebRtcNetEQ_InitVAD(&inst->VADInst, inst->fs);
611 }
612
613 if (len > 0 /* if we decoded any data */
614 && inst->VADInst.VADEnabled /* and VAD enabled */
615 && inst->fs <= 16000) /* can only do VAD for NB and WB */
616 {
617 int VADframeSize; /* VAD frame size in ms */
618 int VADSamplePtr = 0;
619
620 inst->VADInst.VADDecision = 0;
621
622 if (inst->VADInst.VADFunction != NULL) /* make sure that VAD function is provided */
623 {
624 /* divide the data into groups, as large as possible */
625 for (VADframeSize = 30; VADframeSize >= 10; VADframeSize -= 10)
626 {
627 /* loop through 30, 20, 10 */
628
629 while (inst->VADInst.VADDecision == 0
630 && len - VADSamplePtr >= VADframeSize * fs_mult * 8)
631 {
632 /*
633 * Only continue until first active speech found, and as long as there is
634 * one VADframeSize left.
635 */
636
637 /* call VAD with new decoded data */
638 inst->VADInst.VADDecision |= inst->VADInst.VADFunction(
bjornv@webrtc.orgb38fca12012-06-19 11:03:32 +0000639 inst->VADInst.VADState, (int) inst->fs,
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000640 (int16_t *) &pw16_decoded_buffer[VADSamplePtr],
bjornv@webrtc.orgb38fca12012-06-19 11:03:32 +0000641 (VADframeSize * fs_mult * 8));
niklase@google.com470e71d2011-07-07 08:21:25 +0000642
643 VADSamplePtr += VADframeSize * fs_mult * 8; /* increment sample counter */
644 }
645 }
646 }
647 else
648 { /* VAD function is NULL */
649 inst->VADInst.VADDecision = 1; /* set decision to active */
650 inst->VADInst.VADEnabled = 0; /* disable VAD since we have no VAD function */
651 }
652
653 }
654#endif /* NETEQ_VAD */
655
656 /* Adjust timestamp if needed */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000657 uw16_tmp = (uint16_t) inst->pw16_readAddress[1];
658 inst->endTimestamp += (((uint32_t) uw16_tmp) << 16);
659 uw16_tmp = (uint16_t) inst->pw16_readAddress[2];
niklase@google.com470e71d2011-07-07 08:21:25 +0000660 inst->endTimestamp += uw16_tmp;
661
662 if (BGNonly && len > 0)
663 {
664 /*
665 * If BGN mode, we did not produce any data at decoding.
666 * Do it now instead.
667 */
668
669 WebRtcNetEQ_GenerateBGN(inst,
670#ifdef SCRATCH
671 pw16_scratchPtr + SCRATCH_NETEQ_EXPAND,
672#endif
673 pw16_decoded_buffer, len);
674 }
675
676 /* Switch on the instruction received from the MCU side. */
677 switch (instr)
678 {
679 case DSP_INSTR_NORMAL:
680
681 /* Allow for signal processing to apply gain-back etc */
682 WebRtcNetEQ_Normal(inst,
683#ifdef SCRATCH
684 pw16_scratchPtr + SCRATCH_NETEQ_NORMAL,
685#endif
686 pw16_decoded_buffer, len, pw16_NetEqAlgorithm_buffer, &len);
687
688 /* If last packet was decoded as a inband CNG set mode to CNG instead */
689 if ((speechType == TYPE_CNG) || ((inst->w16_mode == MODE_CODEC_INTERNAL_CNG)
690 && (len == 0)))
691 {
692 inst->w16_mode = MODE_CODEC_INTERNAL_CNG;
693 }
694
695#ifdef NETEQ_ATEVENT_DECODE
696 if (playDtmf == 0)
697 {
698 inst->DTMFInst.reinit = 1;
699 }
700#endif
701 break;
702 case DSP_INSTR_NORMAL_ONE_DESC:
703
704 /* Allow for signal processing to apply gain-back etc */
705 WebRtcNetEQ_Normal(inst,
706#ifdef SCRATCH
707 pw16_scratchPtr + SCRATCH_NETEQ_NORMAL,
708#endif
709 pw16_decoded_buffer, len, pw16_NetEqAlgorithm_buffer, &len);
710#ifdef NETEQ_ATEVENT_DECODE
711 if (playDtmf == 0)
712 {
713 inst->DTMFInst.reinit = 1;
714 }
715#endif
716 inst->w16_mode = MODE_ONE_DESCRIPTOR;
717 break;
718 case DSP_INSTR_MERGE:
719#ifdef NETEQ_DELAY_LOGGING
720 temp_var = NETEQ_DELAY_LOGGING_SIGNAL_MERGE_INFO;
leozwang@webrtc.org354b0ed2012-06-01 17:46:21 +0000721 if (fwrite(&temp_var, sizeof(int), 1, delay_fid2) != 1) {
722 return -1;
723 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000724 temp_var = -len;
725#endif
726 /* Call Merge with history*/
727 return_value = WebRtcNetEQ_Merge(inst,
728#ifdef SCRATCH
729 pw16_scratchPtr + SCRATCH_NETEQ_MERGE,
730#endif
731 pw16_decoded_buffer, len, pw16_NetEqAlgorithm_buffer, &len);
732
733 if (return_value < 0)
734 {
735 /* error */
736 return return_value;
737 }
738
739#ifdef NETEQ_DELAY_LOGGING
740 temp_var += len;
leozwang@webrtc.org354b0ed2012-06-01 17:46:21 +0000741 if (fwrite(&temp_var, sizeof(int), 1, delay_fid2) != 1) {
742 return -1;
743 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000744#endif
745 /* If last packet was decoded as a inband CNG set mode to CNG instead */
746 if (speechType == TYPE_CNG) inst->w16_mode = MODE_CODEC_INTERNAL_CNG;
747#ifdef NETEQ_ATEVENT_DECODE
748 if (playDtmf == 0)
749 {
750 inst->DTMFInst.reinit = 1;
751 }
752#endif
753 break;
754
755 case DSP_INSTR_EXPAND:
756 len = 0;
757 pos = 0;
758 while ((inst->endPosition - inst->curPosition - inst->ExpandInst.w16_overlap + pos)
759 < (inst->timestampsPerCall))
760 {
761 return_value = WebRtcNetEQ_Expand(inst,
762#ifdef SCRATCH
763 pw16_scratchPtr + SCRATCH_NETEQ_EXPAND,
764#endif
765 pw16_NetEqAlgorithm_buffer, &len, BGNonly);
766 if (return_value < 0)
767 {
768 /* error */
769 return return_value;
770 }
771
772 /*
773 * Update buffer, but only end part (otherwise expand state is destroyed
774 * since it reuses speechBuffer[] memory
775 */
776
777 WEBRTC_SPL_MEMMOVE_W16(inst->pw16_speechHistory,
778 inst->pw16_speechHistory + len,
779 (inst->w16_speechHistoryLen-len));
780 WEBRTC_SPL_MEMCPY_W16(&inst->pw16_speechHistory[inst->w16_speechHistoryLen-len],
781 pw16_NetEqAlgorithm_buffer, len);
782
783 inst->curPosition -= len;
784
785 /* Update variables for VQmon */
786 inst->w16_concealedTS += len;
787#ifdef NETEQ_DELAY_LOGGING
788 temp_var = NETEQ_DELAY_LOGGING_SIGNAL_EXPAND_INFO;
leozwang@webrtc.org354b0ed2012-06-01 17:46:21 +0000789 if (fwrite(&temp_var, sizeof(int), 1, delay_fid2) != 1) {
790 return -1;
791 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000792 temp_var = len;
leozwang@webrtc.org354b0ed2012-06-01 17:46:21 +0000793 if (fwrite(&temp_var, sizeof(int), 1, delay_fid2) != 1) {
794 return -1;
795 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000796#endif
797 len = 0; /* already written the data, so do not write it again further down. */
798 }
799#ifdef NETEQ_ATEVENT_DECODE
800 if (playDtmf == 0)
801 {
802 inst->DTMFInst.reinit = 1;
803 }
804#endif
805 break;
806
807 case DSP_INSTR_ACCELERATE:
808 if (len < 3 * 80 * fs_mult)
809 {
810 /* We need to move data from the speechBuffer[] in order to get 30 ms */
811 borrowedSamples = 3 * 80 * fs_mult - len;
812
813 WEBRTC_SPL_MEMMOVE_W16(&pw16_decoded_buffer[borrowedSamples],
814 pw16_decoded_buffer, len);
815 WEBRTC_SPL_MEMCPY_W16(pw16_decoded_buffer,
816 &(inst->speechBuffer[inst->endPosition-borrowedSamples]),
817 borrowedSamples);
818
819 return_value = WebRtcNetEQ_Accelerate(inst,
820#ifdef SCRATCH
821 pw16_scratchPtr + SCRATCH_NETEQ_ACCELERATE,
822#endif
823 pw16_decoded_buffer, 3 * inst->timestampsPerCall,
824 pw16_NetEqAlgorithm_buffer, &len, BGNonly);
825
826 if (return_value < 0)
827 {
828 /* error */
829 return return_value;
830 }
831
832 /* Copy back samples to the buffer */
833 if (len < borrowedSamples)
834 {
835 /*
836 * This destroys the beginning of the buffer, but will not cause any
837 * problems
838 */
839
840 WEBRTC_SPL_MEMCPY_W16(&inst->speechBuffer[inst->endPosition-borrowedSamples],
841 pw16_NetEqAlgorithm_buffer, len);
842 WEBRTC_SPL_MEMMOVE_W16(&inst->speechBuffer[borrowedSamples-len],
843 inst->speechBuffer,
844 (inst->endPosition-(borrowedSamples-len)));
845
846 inst->curPosition += (borrowedSamples - len);
847#ifdef NETEQ_DELAY_LOGGING
848 temp_var = NETEQ_DELAY_LOGGING_SIGNAL_ACCELERATE_INFO;
leozwang@webrtc.org354b0ed2012-06-01 17:46:21 +0000849 if (fwrite(&temp_var, sizeof(int), 1, delay_fid2) != 1) {
850 return -1;
851 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000852 temp_var = 3 * inst->timestampsPerCall - len;
leozwang@webrtc.org354b0ed2012-06-01 17:46:21 +0000853 if (fwrite(&temp_var, sizeof(int), 1, delay_fid2) != 1) {
854 return -1;
855 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000856#endif
857 len = 0;
858 }
859 else
860 {
861 WEBRTC_SPL_MEMCPY_W16(&inst->speechBuffer[inst->endPosition-borrowedSamples],
862 pw16_NetEqAlgorithm_buffer, borrowedSamples);
863 WEBRTC_SPL_MEMMOVE_W16(pw16_NetEqAlgorithm_buffer,
864 &pw16_NetEqAlgorithm_buffer[borrowedSamples],
865 (len-borrowedSamples));
866#ifdef NETEQ_DELAY_LOGGING
867 temp_var = NETEQ_DELAY_LOGGING_SIGNAL_ACCELERATE_INFO;
leozwang@webrtc.org354b0ed2012-06-01 17:46:21 +0000868 if (fwrite(&temp_var, sizeof(int), 1, delay_fid2) != 1) {
869 return -1;
870 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000871 temp_var = 3 * inst->timestampsPerCall - len;
leozwang@webrtc.org354b0ed2012-06-01 17:46:21 +0000872 if (fwrite(&temp_var, sizeof(int), 1, delay_fid2) != 1) {
873 return -1;
874 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000875#endif
876 len = len - borrowedSamples;
877 }
878
879 }
880 else
881 {
882#ifdef NETEQ_DELAY_LOGGING
883 temp_var = NETEQ_DELAY_LOGGING_SIGNAL_ACCELERATE_INFO;
leozwang@webrtc.org354b0ed2012-06-01 17:46:21 +0000884 if (fwrite(&temp_var, sizeof(int), 1, delay_fid2) != 1) {
885 return -1;
886 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000887 temp_var = len;
888#endif
889 return_value = WebRtcNetEQ_Accelerate(inst,
890#ifdef SCRATCH
891 pw16_scratchPtr + SCRATCH_NETEQ_ACCELERATE,
892#endif
893 pw16_decoded_buffer, len, pw16_NetEqAlgorithm_buffer, &len, BGNonly);
894
895 if (return_value < 0)
896 {
897 /* error */
898 return return_value;
899 }
900
901#ifdef NETEQ_DELAY_LOGGING
902 temp_var -= len;
leozwang@webrtc.org354b0ed2012-06-01 17:46:21 +0000903 if (fwrite(&temp_var, sizeof(int), 1, delay_fid2) != 1) {
904 return -1;
905 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000906#endif
907 }
908 /* If last packet was decoded as a inband CNG set mode to CNG instead */
909 if (speechType == TYPE_CNG) inst->w16_mode = MODE_CODEC_INTERNAL_CNG;
910#ifdef NETEQ_ATEVENT_DECODE
911 if (playDtmf == 0)
912 {
913 inst->DTMFInst.reinit = 1;
914 }
915#endif
916 break;
917
918 case DSP_INSTR_DO_RFC3389CNG:
919#ifdef NETEQ_CNG_CODEC
920 if (blockLen > 0)
921 {
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000922 if (WebRtcCng_UpdateSid(inst->CNG_Codec_inst, (uint8_t*) blockPtr,
niklase@google.com470e71d2011-07-07 08:21:25 +0000923 payloadLen) < 0)
924 {
925 /* error returned from CNG function */
926 return_value = -WebRtcCng_GetErrorCodeDec(inst->CNG_Codec_inst);
927 len = inst->timestampsPerCall;
928 WebRtcSpl_MemSetW16(pw16_NetEqAlgorithm_buffer, 0, len);
929 break;
930 }
931 }
932
933 if (BGNonly)
934 {
935 /* Get data from BGN function instead of CNG */
936 len = WebRtcNetEQ_GenerateBGN(inst,
937#ifdef SCRATCH
938 pw16_scratchPtr + SCRATCH_NETEQ_EXPAND,
939#endif
940 pw16_NetEqAlgorithm_buffer, inst->timestampsPerCall);
941 if (len != inst->timestampsPerCall)
942 {
943 /* this is not good, treat this as an error */
944 return_value = -1;
945 }
946 }
947 else
948 {
949 return_value = WebRtcNetEQ_Cng(inst, pw16_NetEqAlgorithm_buffer,
950 inst->timestampsPerCall);
951 }
952 len = inst->timestampsPerCall;
953 inst->ExpandInst.w16_consecExp = 0;
954 inst->w16_mode = MODE_RFC3389CNG;
955#ifdef NETEQ_ATEVENT_DECODE
956 if (playDtmf == 0)
957 {
958 inst->DTMFInst.reinit = 1;
959 }
960#endif
961
962 if (return_value < 0)
963 {
964 /* error returned */
965 WebRtcSpl_MemSetW16(pw16_NetEqAlgorithm_buffer, 0, len);
966 }
967
968 break;
969#else
970 return FAULTY_INSTRUCTION;
971#endif
972 case DSP_INSTR_DO_CODEC_INTERNAL_CNG:
973 /*
974 * This represents the case when there is no transmission and the decoder should
975 * do internal CNG.
976 */
977 len = 0;
978 if (inst->codec_ptr_inst.funcDecode != NULL && !BGNonly)
979 {
980 len = inst->codec_ptr_inst.funcDecode(inst->codec_ptr_inst.codec_state,
981 blockPtr, 0, pw16_decoded_buffer, &speechType);
982 }
983 else
984 {
985 /* get BGN data */
986 len = WebRtcNetEQ_GenerateBGN(inst,
987#ifdef SCRATCH
988 pw16_scratchPtr + SCRATCH_NETEQ_EXPAND,
989#endif
990 pw16_decoded_buffer, inst->timestampsPerCall);
991 }
992 WebRtcNetEQ_Normal(inst,
993#ifdef SCRATCH
994 pw16_scratchPtr + SCRATCH_NETEQ_NORMAL,
995#endif
996 pw16_decoded_buffer, len, pw16_NetEqAlgorithm_buffer, &len);
997 inst->w16_mode = MODE_CODEC_INTERNAL_CNG;
998 inst->ExpandInst.w16_consecExp = 0;
999 break;
1000
1001 case DSP_INSTR_DTMF_GENERATE:
1002#ifdef NETEQ_ATEVENT_DECODE
1003 dtmfSwitch = 0;
1004 if ((inst->w16_mode != MODE_DTMF) && (inst->DTMFInst.reinit == 0))
1005 {
1006 /* Special case; see below.
1007 * We must catch this before calling DTMFGenerate,
1008 * since reinit is set to 0 in that call.
1009 */
1010 dtmfSwitch = 1;
1011 }
1012
1013 len = WebRtcNetEQ_DTMFGenerate(&inst->DTMFInst, dtmfValue, dtmfVolume,
1014 pw16_NetEqAlgorithm_buffer, inst->fs, -1);
1015 if (len < 0)
1016 {
1017 /* error occurred */
1018 return_value = len;
1019 len = inst->timestampsPerCall;
1020 WebRtcSpl_MemSetW16(pw16_NetEqAlgorithm_buffer, 0, len);
1021 }
1022
1023 if (dtmfSwitch == 1)
1024 {
1025 /*
1026 * This is the special case where the previous operation was DTMF overdub.
1027 * but the current instruction is "regular" DTMF. We must make sure that the
1028 * DTMF does not have any discontinuities. The first DTMF sample that we
1029 * generate now must be played out immediately, wherefore it must be copied to
1030 * the speech buffer.
1031 */
1032
1033 /*
1034 * Generate extra DTMF data to fill the space between
1035 * curPosition and endPosition
1036 */
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001037 int16_t tempLen;
niklase@google.com470e71d2011-07-07 08:21:25 +00001038
1039 tempLen = WebRtcNetEQ_DTMFGenerate(&inst->DTMFInst, dtmfValue, dtmfVolume,
1040 &pw16_NetEqAlgorithm_buffer[len], inst->fs,
1041 inst->endPosition - inst->curPosition);
1042 if (tempLen < 0)
1043 {
1044 /* error occurred */
1045 return_value = tempLen;
1046 len = inst->endPosition - inst->curPosition;
1047 WebRtcSpl_MemSetW16(pw16_NetEqAlgorithm_buffer, 0,
1048 inst->endPosition - inst->curPosition);
1049 }
1050
1051 /* Add to total length */
1052 len += tempLen;
1053
1054 /* Overwrite the "future" part of the speech buffer with the new DTMF data */
1055
1056 WEBRTC_SPL_MEMCPY_W16(&inst->speechBuffer[inst->curPosition],
1057 pw16_NetEqAlgorithm_buffer,
1058 inst->endPosition - inst->curPosition);
1059
1060 /* Shuffle the remaining data to the beginning of algorithm buffer */
1061 len -= (inst->endPosition - inst->curPosition);
1062 WEBRTC_SPL_MEMMOVE_W16(pw16_NetEqAlgorithm_buffer,
1063 &pw16_NetEqAlgorithm_buffer[inst->endPosition - inst->curPosition],
1064 len);
1065 }
1066
1067 inst->endTimestamp += inst->timestampsPerCall;
1068 inst->DTMFInst.reinit = 0;
1069 inst->ExpandInst.w16_consecExp = 0;
1070 inst->w16_mode = MODE_DTMF;
1071 BGNonly = 0; /* override BGN only and let DTMF through */
1072
1073 playDtmf = 0; /* set to zero because the DTMF is already in the Algorithm buffer */
1074 /*
1075 * If playDtmf is 1, an extra DTMF vector will be generated and overdubbed
1076 * on the output.
1077 */
1078
1079#ifdef NETEQ_STEREO
1080 if (msInfo->msMode == NETEQ_MASTER)
1081 {
1082 /* signal to slave that master is using DTMF only */
1083 msInfo->extraInfo = DTMF_ONLY;
1084 }
1085#endif
1086
1087 break;
1088#else
1089 inst->w16_mode = MODE_ERROR;
1090 dspInfo->lastMode = MODE_ERROR;
1091 return FAULTY_INSTRUCTION;
1092#endif
1093
1094 case DSP_INSTR_DO_ALTERNATIVE_PLC:
1095 if (inst->codec_ptr_inst.funcDecodePLC != 0)
1096 {
1097 len = inst->codec_ptr_inst.funcDecodePLC(inst->codec_ptr_inst.codec_state,
1098 pw16_NetEqAlgorithm_buffer, 1);
1099 }
1100 else
1101 {
1102 len = inst->timestampsPerCall;
1103 /* ZeroStuffing... */
1104 WebRtcSpl_MemSetW16(pw16_NetEqAlgorithm_buffer, 0, len);
roosa@google.comb8ba4d82012-12-14 00:06:18 +00001105 /* By not advancing the timestamp, NetEq inserts samples. */
1106 inst->statInst.addedSamples += len;
niklase@google.com470e71d2011-07-07 08:21:25 +00001107 }
1108 inst->ExpandInst.w16_consecExp = 0;
1109 break;
1110 case DSP_INSTR_DO_ALTERNATIVE_PLC_INC_TS:
1111 if (inst->codec_ptr_inst.funcDecodePLC != 0)
1112 {
1113 len = inst->codec_ptr_inst.funcDecodePLC(inst->codec_ptr_inst.codec_state,
1114 pw16_NetEqAlgorithm_buffer, 1);
1115 }
1116 else
1117 {
1118 len = inst->timestampsPerCall;
1119 /* ZeroStuffing... */
1120 WebRtcSpl_MemSetW16(pw16_NetEqAlgorithm_buffer, 0, len);
1121 }
1122 inst->ExpandInst.w16_consecExp = 0;
1123 inst->endTimestamp += len;
1124 break;
1125 case DSP_INSTR_DO_AUDIO_REPETITION:
1126 len = inst->timestampsPerCall;
1127 /* copy->paste... */
1128 WEBRTC_SPL_MEMCPY_W16(pw16_NetEqAlgorithm_buffer,
1129 &inst->speechBuffer[inst->endPosition-len], len);
1130 inst->ExpandInst.w16_consecExp = 0;
1131 break;
1132 case DSP_INSTR_DO_AUDIO_REPETITION_INC_TS:
1133 len = inst->timestampsPerCall;
1134 /* copy->paste... */
1135 WEBRTC_SPL_MEMCPY_W16(pw16_NetEqAlgorithm_buffer,
1136 &inst->speechBuffer[inst->endPosition-len], len);
1137 inst->ExpandInst.w16_consecExp = 0;
1138 inst->endTimestamp += len;
1139 break;
1140
1141 case DSP_INSTR_PREEMPTIVE_EXPAND:
1142 if (len < 3 * inst->timestampsPerCall)
1143 {
1144 /* borrow samples from sync buffer if necessary */
1145 borrowedSamples = 3 * inst->timestampsPerCall - len; /* borrow this many samples */
1146 /* calculate how many of these are already played out */
1147 oldBorrowedSamples = WEBRTC_SPL_MAX(0,
1148 borrowedSamples - (inst->endPosition - inst->curPosition));
1149 WEBRTC_SPL_MEMMOVE_W16(&pw16_decoded_buffer[borrowedSamples],
1150 pw16_decoded_buffer, len);
1151 WEBRTC_SPL_MEMCPY_W16(pw16_decoded_buffer,
1152 &(inst->speechBuffer[inst->endPosition-borrowedSamples]),
1153 borrowedSamples);
1154 }
1155 else
1156 {
1157 borrowedSamples = 0;
1158 oldBorrowedSamples = 0;
1159 }
1160
1161#ifdef NETEQ_DELAY_LOGGING
1162 w16_tmp1 = len;
1163#endif
1164 /* do the expand */
1165 return_value = WebRtcNetEQ_PreEmptiveExpand(inst,
1166#ifdef SCRATCH
1167 /* use same scratch memory as Accelerate */
1168 pw16_scratchPtr + SCRATCH_NETEQ_ACCELERATE,
1169#endif
1170 pw16_decoded_buffer, len + borrowedSamples, oldBorrowedSamples,
1171 pw16_NetEqAlgorithm_buffer, &len, BGNonly);
1172
1173 if (return_value < 0)
1174 {
1175 /* error */
1176 return return_value;
1177 }
1178
1179 if (borrowedSamples > 0)
1180 {
1181 /* return borrowed samples */
1182
1183 /* Copy back to last part of speechBuffer from beginning of output buffer */
1184 WEBRTC_SPL_MEMCPY_W16( &(inst->speechBuffer[inst->endPosition-borrowedSamples]),
1185 pw16_NetEqAlgorithm_buffer,
1186 borrowedSamples);
1187
1188 len -= borrowedSamples; /* remove the borrowed samples from new total length */
1189
1190 /* Move to beginning of output buffer from end of output buffer */
1191 WEBRTC_SPL_MEMMOVE_W16( pw16_NetEqAlgorithm_buffer,
1192 &pw16_NetEqAlgorithm_buffer[borrowedSamples],
1193 len);
1194 }
1195
1196#ifdef NETEQ_DELAY_LOGGING
1197 temp_var = NETEQ_DELAY_LOGGING_SIGNAL_PREEMPTIVE_INFO;
leozwang@webrtc.org354b0ed2012-06-01 17:46:21 +00001198 if (fwrite(&temp_var, sizeof(int), 1, delay_fid2) != 1) {
1199 return -1;
1200 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001201 temp_var = len - w16_tmp1; /* number of samples added */
leozwang@webrtc.org354b0ed2012-06-01 17:46:21 +00001202 if (fwrite(&temp_var, sizeof(int), 1, delay_fid2) != 1) {
1203 return -1;
1204 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001205#endif
1206 /* If last packet was decoded as inband CNG, set mode to CNG instead */
1207 if (speechType == TYPE_CNG) inst->w16_mode = MODE_CODEC_INTERNAL_CNG;
1208#ifdef NETEQ_ATEVENT_DECODE
1209 if (playDtmf == 0)
1210 {
1211 inst->DTMFInst.reinit = 1;
1212 }
1213#endif
1214 break;
1215
1216 case DSP_INSTR_FADE_TO_BGN:
1217 {
1218 int tempReturnValue;
1219 /* do not overwrite return_value, since it likely contains an error code */
1220
1221 /* calculate interpolation length */
1222 w16_tmp3 = WEBRTC_SPL_MIN(inst->endPosition - inst->curPosition,
1223 inst->timestampsPerCall);
1224 /* check that it will fit in pw16_NetEqAlgorithm_buffer */
1225 if (w16_tmp3 + inst->w16_frameLen > NETEQ_MAX_OUTPUT_SIZE)
1226 {
1227 w16_tmp3 = NETEQ_MAX_OUTPUT_SIZE - inst->w16_frameLen;
1228 }
1229
1230 /* call Expand */
1231 len = inst->timestampsPerCall + inst->ExpandInst.w16_overlap;
1232 pos = 0;
1233
1234 tempReturnValue = WebRtcNetEQ_Expand(inst,
1235#ifdef SCRATCH
1236 pw16_scratchPtr + SCRATCH_NETEQ_EXPAND,
1237#endif
1238 pw16_NetEqAlgorithm_buffer, &len, 1);
1239
1240 if (tempReturnValue < 0)
1241 {
1242 /* error */
1243 /* this error value will override return_value */
1244 return tempReturnValue;
1245 }
1246
1247 pos += len; /* got len samples from expand */
1248
1249 /* copy to fill the demand */
1250 while (pos + len <= inst->w16_frameLen + w16_tmp3)
1251 {
1252 WEBRTC_SPL_MEMCPY_W16(&pw16_NetEqAlgorithm_buffer[pos],
1253 pw16_NetEqAlgorithm_buffer, len);
1254 pos += len;
1255 }
1256
1257 /* fill with fraction of the expand vector if needed */
1258 if (pos < inst->w16_frameLen + w16_tmp3)
1259 {
1260 WEBRTC_SPL_MEMCPY_W16(&pw16_NetEqAlgorithm_buffer[pos], pw16_NetEqAlgorithm_buffer,
1261 inst->w16_frameLen + w16_tmp3 - pos);
1262 }
1263
1264 len = inst->w16_frameLen + w16_tmp3; /* truncate any surplus samples since we don't want these */
1265
1266 /*
1267 * Mix with contents in sync buffer. Find largest power of two that is less than
1268 * interpolate length divide 16384 with this number; result is in w16_tmp2.
1269 */
1270 w16_tmp1 = 2;
1271 w16_tmp2 = 16384;
1272 while (w16_tmp1 <= w16_tmp3)
1273 {
1274 w16_tmp2 >>= 1; /* divide with 2 */
1275 w16_tmp1 <<= 1; /* increase with a factor of 2 */
1276 }
1277
1278 w16_tmp1 = 0;
1279 pos = 0;
1280 while (w16_tmp1 < 16384)
1281 {
1282 inst->speechBuffer[inst->curPosition + pos]
1283 =
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001284 (int16_t) WEBRTC_SPL_RSHIFT_W32(
niklase@google.com470e71d2011-07-07 08:21:25 +00001285 WEBRTC_SPL_MUL_16_16( inst->speechBuffer[inst->endPosition - w16_tmp3 + pos],
1286 16384-w16_tmp1 ) +
1287 WEBRTC_SPL_MUL_16_16( pw16_NetEqAlgorithm_buffer[pos], w16_tmp1 ),
1288 14 );
1289 w16_tmp1 += w16_tmp2;
1290 pos++;
1291 }
1292
1293 /* overwrite remainder of speech buffer */
1294
1295 WEBRTC_SPL_MEMCPY_W16( &inst->speechBuffer[inst->endPosition - w16_tmp3 + pos],
1296 &pw16_NetEqAlgorithm_buffer[pos], w16_tmp3 - pos);
1297
1298 len -= w16_tmp3;
1299 /* shift algorithm buffer */
1300
1301 WEBRTC_SPL_MEMMOVE_W16( pw16_NetEqAlgorithm_buffer,
1302 &pw16_NetEqAlgorithm_buffer[w16_tmp3],
1303 len );
1304
1305 /* Update variables for VQmon */
1306 inst->w16_concealedTS += len;
1307
1308 inst->w16_mode = MODE_FADE_TO_BGN;
1309#ifdef NETEQ_DELAY_LOGGING
1310 temp_var = NETEQ_DELAY_LOGGING_SIGNAL_EXPAND_INFO;
leozwang@webrtc.org354b0ed2012-06-01 17:46:21 +00001311 if (fwrite(&temp_var, sizeof(int), 1, delay_fid2) != 1) {
1312 return -1;
1313 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001314 temp_var = len;
leozwang@webrtc.org354b0ed2012-06-01 17:46:21 +00001315 if (fwrite(&temp_var, sizeof(int), 1, delay_fid2) != 1) {
1316 return -1;
1317 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001318#endif
1319
1320 break;
1321 }
1322
1323 default:
1324 inst->w16_mode = MODE_ERROR;
1325 dspInfo->lastMode = MODE_ERROR;
1326 return FAULTY_INSTRUCTION;
1327 } /* end of grand switch */
1328
1329 /* Copy data directly to output buffer */
1330
1331 w16_tmp2 = 0;
1332 if ((inst->endPosition + len - inst->curPosition - inst->ExpandInst.w16_overlap)
1333 >= inst->timestampsPerCall)
1334 {
1335 w16_tmp2 = inst->endPosition - inst->curPosition;
1336 w16_tmp2 = WEBRTC_SPL_MAX(w16_tmp2, 0); /* Additional error protection, just in case */
1337 w16_tmp1 = WEBRTC_SPL_MIN(w16_tmp2, inst->timestampsPerCall);
1338 w16_tmp2 = inst->timestampsPerCall - w16_tmp1;
1339 WEBRTC_SPL_MEMCPY_W16(pw16_outData, &inst->speechBuffer[inst->curPosition], w16_tmp1);
1340 WEBRTC_SPL_MEMCPY_W16(&pw16_outData[w16_tmp1], pw16_NetEqAlgorithm_buffer, w16_tmp2);
1341 DataEnough = 1;
1342 }
1343 else
1344 {
1345 DataEnough = 0;
1346 }
1347
1348 if (playDtmf != 0)
1349 {
henrik.lundin@webrtc.org44ef3772011-12-07 10:43:25 +00001350#ifdef NETEQ_ATEVENT_DECODE
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001351 int16_t outDataIndex = 0;
1352 int16_t overdubLen = -1; /* default len */
1353 int16_t dtmfLen;
niklase@google.com470e71d2011-07-07 08:21:25 +00001354
1355 /*
1356 * Overdub the output with DTMF. Note that this is not executed if the
1357 * DSP_INSTR_DTMF_GENERATE operation is performed above.
1358 */
niklase@google.com470e71d2011-07-07 08:21:25 +00001359 if (inst->DTMFInst.lastDtmfSample - inst->curPosition > 0)
1360 {
1361 /* special operation for transition from "DTMF only" to "DTMF overdub" */
1362 outDataIndex
1363 = WEBRTC_SPL_MIN(inst->DTMFInst.lastDtmfSample - inst->curPosition,
1364 inst->timestampsPerCall);
1365 overdubLen = inst->timestampsPerCall - outDataIndex;
1366 }
1367
1368 dtmfLen = WebRtcNetEQ_DTMFGenerate(&inst->DTMFInst, dtmfValue, dtmfVolume,
1369 &pw16_outData[outDataIndex], inst->fs, overdubLen);
1370 if (dtmfLen < 0)
1371 {
1372 /* error occurred */
1373 return_value = dtmfLen;
1374 }
1375 inst->DTMFInst.reinit = 0;
1376#else
1377 inst->w16_mode = MODE_ERROR;
1378 dspInfo->lastMode = MODE_ERROR;
1379 return FAULTY_INSTRUCTION;
1380#endif
1381 }
1382
1383 /*
1384 * Shuffle speech buffer to allow more data. Move data from pw16_NetEqAlgorithm_buffer
1385 * to speechBuffer.
1386 */
1387 if (instr != DSP_INSTR_EXPAND)
1388 {
1389 w16_tmp1 = WEBRTC_SPL_MIN(inst->endPosition, len);
1390 WEBRTC_SPL_MEMMOVE_W16(inst->speechBuffer, inst->speechBuffer + w16_tmp1,
1391 (inst->endPosition-w16_tmp1));
1392 WEBRTC_SPL_MEMCPY_W16(&inst->speechBuffer[inst->endPosition-w16_tmp1],
1393 &pw16_NetEqAlgorithm_buffer[len-w16_tmp1], w16_tmp1);
1394#ifdef NETEQ_ATEVENT_DECODE
1395 /* Update index to end of DTMF data in speech buffer */
1396 if (instr == DSP_INSTR_DTMF_GENERATE)
1397 {
1398 /* We have written DTMF data to the end of speech buffer */
1399 inst->DTMFInst.lastDtmfSample = inst->endPosition;
1400 }
1401 else if (inst->DTMFInst.lastDtmfSample > 0)
1402 {
1403 /* The end of DTMF data in speech buffer has been shuffled */
1404 inst->DTMFInst.lastDtmfSample -= w16_tmp1;
1405 }
1406#endif
1407 /*
1408 * Update the BGN history if last operation was not expand (nor Merge, Accelerate
1409 * or Pre-emptive expand, to save complexity).
1410 */
1411 if ((inst->w16_mode != MODE_EXPAND) && (inst->w16_mode != MODE_MERGE)
1412 && (inst->w16_mode != MODE_SUCCESS_ACCELERATE) && (inst->w16_mode
1413 != MODE_LOWEN_ACCELERATE) && (inst->w16_mode != MODE_SUCCESS_PREEMPTIVE)
1414 && (inst->w16_mode != MODE_LOWEN_PREEMPTIVE) && (inst->w16_mode
1415 != MODE_FADE_TO_BGN) && (inst->w16_mode != MODE_DTMF) && (!BGNonly))
1416 {
1417 WebRtcNetEQ_BGNUpdate(inst
1418#ifdef SCRATCH
1419 , pw16_scratchPtr + SCRATCH_NETEQ_BGN_UPDATE
1420#endif
1421 );
1422 }
1423 }
1424 else /* instr == DSP_INSTR_EXPAND */
1425 {
1426 /* Nothing should be done since data is already copied to output. */
1427 }
1428
1429 inst->curPosition -= len;
1430
1431 /*
1432 * Extra protection in case something should go totally wrong in terms of sizes...
1433 * If everything is ok this should NEVER happen.
1434 */
1435 if (inst->curPosition < -inst->timestampsPerCall)
1436 {
1437 inst->curPosition = -inst->timestampsPerCall;
1438 }
1439
1440 if ((instr != DSP_INSTR_EXPAND) && (instr != DSP_INSTR_MERGE) && (instr
1441 != DSP_INSTR_FADE_TO_BGN))
1442 {
1443 /* Reset concealed TS parameter if it does not seem to have been flushed */
1444 if (inst->w16_concealedTS > inst->timestampsPerCall)
1445 {
1446 inst->w16_concealedTS = 0;
1447 }
1448 }
1449
1450 /*
1451 * Double-check that we actually have 10 ms to play. If we haven't, there has been a
1452 * serious error.The decoder might have returned way too few samples
1453 */
1454 if (!DataEnough)
1455 {
1456 /* This should not happen. Set outdata to zeros, and return error. */
1457 WebRtcSpl_MemSetW16(pw16_outData, 0, inst->timestampsPerCall);
1458 *pw16_len = inst->timestampsPerCall;
1459 inst->w16_mode = MODE_ERROR;
1460 dspInfo->lastMode = MODE_ERROR;
1461 return RECOUT_ERROR_SAMPLEUNDERRUN;
1462 }
1463
1464 /*
1465 * Update Videosync timestamp (this special timestamp is needed since the endTimestamp
1466 * stops during CNG and Expand periods.
1467 */
1468 if ((inst->w16_mode != MODE_EXPAND) && (inst->w16_mode != MODE_RFC3389CNG))
1469 {
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001470 uint32_t uw32_tmpTS;
niklase@google.com470e71d2011-07-07 08:21:25 +00001471 uw32_tmpTS = inst->endTimestamp - (inst->endPosition - inst->curPosition);
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001472 if ((int32_t) (uw32_tmpTS - inst->videoSyncTimestamp) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001473 {
1474 inst->videoSyncTimestamp = uw32_tmpTS;
1475 }
1476 }
1477 else
1478 {
1479 inst->videoSyncTimestamp += inst->timestampsPerCall;
1480 }
1481
1482 /* After this, regardless of what has happened, deliver 10 ms of future data */
1483 inst->curPosition += inst->timestampsPerCall;
1484 *pw16_len = inst->timestampsPerCall;
1485
1486 /* Remember if BGNonly was used */
1487 if (BGNonly)
1488 {
1489 inst->w16_mode |= MODE_BGN_ONLY;
1490 }
1491
1492 return return_value;
1493}
1494
1495#undef SCRATCH_ALGORITHM_BUFFER
1496#undef SCRATCH_NETEQ_NORMAL
1497#undef SCRATCH_NETEQ_MERGE
1498#undef SCRATCH_NETEQ_BGN_UPDATE
1499#undef SCRATCH_NETEQ_EXPAND
1500#undef SCRATCH_DSP_INFO
1501#undef SCRATCH_NETEQ_ACCELERATE
1502#undef SIZE_SCRATCH_BUFFER