233 lines
7.8 KiB
C
233 lines
7.8 KiB
C
|
/*
|
||
|
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||
|
*
|
||
|
* Use of this source code is governed by a BSD-style license
|
||
|
* that can be found in the LICENSE file in the root of the source
|
||
|
* tree. An additional intellectual property rights grant can be found
|
||
|
* in the file PATENTS. All contributing project authors may
|
||
|
* be found in the AUTHORS file in the root of the source tree.
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* Implementation of packet buffer for DTMF messages.
|
||
|
*/
|
||
|
|
||
|
#include "dtmf_buffer.h"
|
||
|
|
||
|
#include "typedefs.h" /* to define endianness */
|
||
|
#include "signal_processing_library.h"
|
||
|
|
||
|
#include "neteq_error_codes.h"
|
||
|
|
||
|
|
||
|
#ifdef NETEQ_ATEVENT_DECODE
|
||
|
|
||
|
WebRtc_Word16 WebRtcNetEQ_DtmfRemoveEvent(dtmf_inst_t *DTMFdec_inst)
|
||
|
{
|
||
|
|
||
|
int i;
|
||
|
for (i = 0; i < 3; i++)
|
||
|
{
|
||
|
DTMFdec_inst->EventQueue[i] = DTMFdec_inst->EventQueue[i + 1];
|
||
|
DTMFdec_inst->EventQueueVolume[i] = DTMFdec_inst->EventQueueVolume[i + 1];
|
||
|
DTMFdec_inst->EventQueueEnded[i] = DTMFdec_inst->EventQueueEnded[i + 1];
|
||
|
DTMFdec_inst->EventQueueStartTime[i] = DTMFdec_inst->EventQueueStartTime[i + 1];
|
||
|
DTMFdec_inst->EventQueueEndTime[i] = DTMFdec_inst->EventQueueEndTime[i + 1];
|
||
|
}
|
||
|
DTMFdec_inst->EventBufferSize--;
|
||
|
DTMFdec_inst->EventQueue[3] = -1;
|
||
|
DTMFdec_inst->EventQueueVolume[3] = 0;
|
||
|
DTMFdec_inst->EventQueueEnded[3] = 0;
|
||
|
DTMFdec_inst->EventQueueStartTime[3] = 0;
|
||
|
DTMFdec_inst->EventQueueEndTime[3] = 0;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
WebRtc_Word16 WebRtcNetEQ_DtmfDecoderInit(dtmf_inst_t *DTMFdec_inst, WebRtc_UWord16 fs,
|
||
|
WebRtc_Word16 MaxPLCtime)
|
||
|
{
|
||
|
int i;
|
||
|
if (((fs != 8000) && (fs != 16000) && (fs != 32000) && (fs != 48000)) || (MaxPLCtime < 0))
|
||
|
{
|
||
|
return DTMF_DEC_PARAMETER_ERROR;
|
||
|
}
|
||
|
if (fs == 8000)
|
||
|
DTMFdec_inst->framelen = 80;
|
||
|
else if (fs == 16000)
|
||
|
DTMFdec_inst->framelen = 160;
|
||
|
else if (fs == 32000)
|
||
|
DTMFdec_inst->framelen = 320;
|
||
|
else
|
||
|
/* fs == 48000 */
|
||
|
DTMFdec_inst->framelen = 480;
|
||
|
|
||
|
DTMFdec_inst->MaxPLCtime = MaxPLCtime;
|
||
|
DTMFdec_inst->CurrentPLCtime = 0;
|
||
|
DTMFdec_inst->EventBufferSize = 0;
|
||
|
for (i = 0; i < 4; i++)
|
||
|
{
|
||
|
DTMFdec_inst->EventQueue[i] = -1;
|
||
|
DTMFdec_inst->EventQueueVolume[i] = 0;
|
||
|
DTMFdec_inst->EventQueueEnded[i] = 0;
|
||
|
DTMFdec_inst->EventQueueStartTime[i] = 0;
|
||
|
DTMFdec_inst->EventQueueEndTime[i] = 0;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
WebRtc_Word16 WebRtcNetEQ_DtmfInsertEvent(dtmf_inst_t *DTMFdec_inst,
|
||
|
const WebRtc_Word16 *encoded, WebRtc_Word16 len,
|
||
|
WebRtc_UWord32 timeStamp)
|
||
|
{
|
||
|
|
||
|
int i;
|
||
|
WebRtc_Word16 value;
|
||
|
const WebRtc_Word16 *EventStart;
|
||
|
WebRtc_Word16 endEvent;
|
||
|
WebRtc_Word16 Volume;
|
||
|
WebRtc_Word16 Duration;
|
||
|
WebRtc_Word16 position = -1;
|
||
|
|
||
|
/* Extract event */
|
||
|
if (len == 4)
|
||
|
{
|
||
|
EventStart = encoded;
|
||
|
#ifdef WEBRTC_BIG_ENDIAN
|
||
|
value=((*EventStart)>>8);
|
||
|
endEvent=((*EventStart)&0x80)>>7;
|
||
|
Volume=((*EventStart)&0x3F);
|
||
|
Duration=EventStart[1];
|
||
|
#else
|
||
|
value = ((*EventStart) & 0xFF);
|
||
|
endEvent = ((*EventStart) & 0x8000) >> 15;
|
||
|
Volume = ((*EventStart) & 0x3F00) >> 8;
|
||
|
Duration = (((((WebRtc_UWord16) EventStart[1]) >> 8) & 0xFF)
|
||
|
| (((WebRtc_UWord16) (EventStart[1] & 0xFF)) << 8));
|
||
|
#endif
|
||
|
/* Only events between 0-15 are supported (DTMF tones) */
|
||
|
if ((value < 0) || (value > 15))
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/* Discard all DTMF tones with really low volume (<-36dbm0) */
|
||
|
if (Volume > 36)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/*Are there any unended events of the same type? */
|
||
|
for (i = 0; i < DTMFdec_inst->EventBufferSize; i++)
|
||
|
{
|
||
|
/* Going through the whole queue even when we have found a match will
|
||
|
ensure that we add to the latest applicable event */
|
||
|
if ((DTMFdec_inst->EventQueue[i] == value) && (!DTMFdec_inst->EventQueueEnded[i]
|
||
|
|| endEvent)) position = i;
|
||
|
}
|
||
|
if (position > -1)
|
||
|
{
|
||
|
DTMFdec_inst->EventQueueVolume[position] = Volume;
|
||
|
if ((timeStamp + Duration) > DTMFdec_inst->EventQueueEndTime[position]) DTMFdec_inst->EventQueueEndTime[position]
|
||
|
= DTMFdec_inst->EventQueueStartTime[position] + Duration;
|
||
|
if (endEvent) DTMFdec_inst->EventQueueEnded[position] = 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (DTMFdec_inst->EventBufferSize == MAX_DTMF_QUEUE_SIZE)
|
||
|
{ /* Buffer full */
|
||
|
/* Remove one event */
|
||
|
DTMFdec_inst->EventBufferSize--;
|
||
|
}
|
||
|
/* Store data in the instance on a new position*/
|
||
|
DTMFdec_inst->EventQueue[DTMFdec_inst->EventBufferSize] = value;
|
||
|
DTMFdec_inst->EventQueueVolume[DTMFdec_inst->EventBufferSize] = Volume;
|
||
|
DTMFdec_inst->EventQueueEnded[DTMFdec_inst->EventBufferSize] = endEvent;
|
||
|
DTMFdec_inst->EventQueueStartTime[DTMFdec_inst->EventBufferSize] = timeStamp;
|
||
|
DTMFdec_inst->EventQueueEndTime[DTMFdec_inst->EventBufferSize] = timeStamp
|
||
|
+ Duration;
|
||
|
DTMFdec_inst->EventBufferSize++;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
return DTMF_INSERT_ERROR;
|
||
|
}
|
||
|
|
||
|
WebRtc_Word16 WebRtcNetEQ_DtmfDecode(dtmf_inst_t *DTMFdec_inst, WebRtc_Word16 *event,
|
||
|
WebRtc_Word16 *volume, WebRtc_UWord32 currTimeStamp)
|
||
|
{
|
||
|
|
||
|
if (DTMFdec_inst->EventBufferSize < 1) return 0; /* No events to play */
|
||
|
|
||
|
/* We have events, is it time to play them? */
|
||
|
if (currTimeStamp < DTMFdec_inst->EventQueueStartTime[0])
|
||
|
{
|
||
|
/*No, just return zero */
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/* Continue on the event that is currently ongoing */
|
||
|
*event = DTMFdec_inst->EventQueue[0];
|
||
|
*volume = DTMFdec_inst->EventQueueVolume[0];
|
||
|
|
||
|
if (DTMFdec_inst->EventQueueEndTime[0] >= (currTimeStamp + DTMFdec_inst->framelen))
|
||
|
{
|
||
|
|
||
|
/* Still at least framLen to play */
|
||
|
|
||
|
DTMFdec_inst->CurrentPLCtime = 0;
|
||
|
if ((DTMFdec_inst->EventQueueEndTime[0] == (currTimeStamp + DTMFdec_inst->framelen))
|
||
|
&& (DTMFdec_inst->EventQueueEnded[0]))
|
||
|
{ /* We are done */
|
||
|
/*Remove the event from Queue*/
|
||
|
WebRtcNetEQ_DtmfRemoveEvent(DTMFdec_inst);
|
||
|
}
|
||
|
return DTMFdec_inst->framelen;
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ((DTMFdec_inst->EventQueueEnded[0]) || (DTMFdec_inst->EventQueue[1] > -1))
|
||
|
{
|
||
|
/*
|
||
|
* Less than frameLen to play and end of event or already received next event.
|
||
|
* Give our a whole frame size of audio to simplify things.
|
||
|
*/
|
||
|
|
||
|
/*Remove the event from Queue*/
|
||
|
WebRtcNetEQ_DtmfRemoveEvent(DTMFdec_inst);
|
||
|
DTMFdec_inst->CurrentPLCtime = 0;
|
||
|
|
||
|
return DTMFdec_inst->framelen;
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* Less than frameLen to play and not end of event. */
|
||
|
DTMFdec_inst->CurrentPLCtime = (WebRtc_Word16) (currTimeStamp
|
||
|
- DTMFdec_inst->EventQueueEndTime[0]);
|
||
|
|
||
|
if ((DTMFdec_inst->CurrentPLCtime > DTMFdec_inst->MaxPLCtime)
|
||
|
|| (DTMFdec_inst->CurrentPLCtime < -DTMFdec_inst->MaxPLCtime))
|
||
|
{
|
||
|
/*Remove the event from queue*/
|
||
|
WebRtcNetEQ_DtmfRemoveEvent(DTMFdec_inst);
|
||
|
DTMFdec_inst->CurrentPLCtime = 0;
|
||
|
}
|
||
|
|
||
|
/* If we have a new event that it's time to play */
|
||
|
if ((DTMFdec_inst->EventQueue[1] > -1) && (DTMFdec_inst->EventQueueStartTime[1]
|
||
|
>= (currTimeStamp + DTMFdec_inst->framelen)))
|
||
|
{
|
||
|
/*Remove the event from queue*/
|
||
|
WebRtcNetEQ_DtmfRemoveEvent(DTMFdec_inst);
|
||
|
DTMFdec_inst->CurrentPLCtime = 0;
|
||
|
}
|
||
|
|
||
|
return DTMFdec_inst->framelen;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|