blob: 9e32126464068227ad2c3f3682cc1090b1d942d1 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11/*
12 * Implementation of packet buffer for DTMF messages.
13 */
14
15#include "dtmf_buffer.h"
16
17#include "typedefs.h" /* to define endianness */
18#include "signal_processing_library.h"
19
20#include "neteq_error_codes.h"
21
22
23#ifdef NETEQ_ATEVENT_DECODE
24
pbos@webrtc.org0946a562013-04-09 00:28:06 +000025int16_t WebRtcNetEQ_DtmfRemoveEvent(dtmf_inst_t *DTMFdec_inst)
niklase@google.com470e71d2011-07-07 08:21:25 +000026{
27
28 int i;
29 for (i = 0; i < 3; i++)
30 {
31 DTMFdec_inst->EventQueue[i] = DTMFdec_inst->EventQueue[i + 1];
32 DTMFdec_inst->EventQueueVolume[i] = DTMFdec_inst->EventQueueVolume[i + 1];
33 DTMFdec_inst->EventQueueEnded[i] = DTMFdec_inst->EventQueueEnded[i + 1];
34 DTMFdec_inst->EventQueueStartTime[i] = DTMFdec_inst->EventQueueStartTime[i + 1];
35 DTMFdec_inst->EventQueueEndTime[i] = DTMFdec_inst->EventQueueEndTime[i + 1];
36 }
37 DTMFdec_inst->EventBufferSize--;
38 DTMFdec_inst->EventQueue[3] = -1;
39 DTMFdec_inst->EventQueueVolume[3] = 0;
40 DTMFdec_inst->EventQueueEnded[3] = 0;
41 DTMFdec_inst->EventQueueStartTime[3] = 0;
42 DTMFdec_inst->EventQueueEndTime[3] = 0;
43
44 return 0;
45}
46
pbos@webrtc.org0946a562013-04-09 00:28:06 +000047int16_t WebRtcNetEQ_DtmfDecoderInit(dtmf_inst_t *DTMFdec_inst, uint16_t fs,
48 int16_t MaxPLCtime)
niklase@google.com470e71d2011-07-07 08:21:25 +000049{
50 int i;
51 if (((fs != 8000) && (fs != 16000) && (fs != 32000) && (fs != 48000)) || (MaxPLCtime < 0))
52 {
53 return DTMF_DEC_PARAMETER_ERROR;
54 }
55 if (fs == 8000)
56 DTMFdec_inst->framelen = 80;
57 else if (fs == 16000)
58 DTMFdec_inst->framelen = 160;
59 else if (fs == 32000)
60 DTMFdec_inst->framelen = 320;
61 else
62 /* fs == 48000 */
63 DTMFdec_inst->framelen = 480;
64
65 DTMFdec_inst->MaxPLCtime = MaxPLCtime;
66 DTMFdec_inst->CurrentPLCtime = 0;
67 DTMFdec_inst->EventBufferSize = 0;
68 for (i = 0; i < 4; i++)
69 {
70 DTMFdec_inst->EventQueue[i] = -1;
71 DTMFdec_inst->EventQueueVolume[i] = 0;
72 DTMFdec_inst->EventQueueEnded[i] = 0;
73 DTMFdec_inst->EventQueueStartTime[i] = 0;
74 DTMFdec_inst->EventQueueEndTime[i] = 0;
75 }
76 return 0;
77}
78
pbos@webrtc.org0946a562013-04-09 00:28:06 +000079int16_t WebRtcNetEQ_DtmfInsertEvent(dtmf_inst_t *DTMFdec_inst,
80 const int16_t *encoded, int16_t len,
81 uint32_t timeStamp)
niklase@google.com470e71d2011-07-07 08:21:25 +000082{
83
84 int i;
pbos@webrtc.org0946a562013-04-09 00:28:06 +000085 int16_t value;
86 const int16_t *EventStart;
87 int16_t endEvent;
88 int16_t Volume;
89 int16_t Duration;
90 int16_t position = -1;
niklase@google.com470e71d2011-07-07 08:21:25 +000091
92 /* Extract event */
93 if (len == 4)
94 {
95 EventStart = encoded;
96#ifdef WEBRTC_BIG_ENDIAN
97 value=((*EventStart)>>8);
98 endEvent=((*EventStart)&0x80)>>7;
99 Volume=((*EventStart)&0x3F);
100 Duration=EventStart[1];
101#else
102 value = ((*EventStart) & 0xFF);
103 endEvent = ((*EventStart) & 0x8000) >> 15;
104 Volume = ((*EventStart) & 0x3F00) >> 8;
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000105 Duration = (((((uint16_t) EventStart[1]) >> 8) & 0xFF)
106 | (((uint16_t) (EventStart[1] & 0xFF)) << 8));
niklase@google.com470e71d2011-07-07 08:21:25 +0000107#endif
108 /* Only events between 0-15 are supported (DTMF tones) */
109 if ((value < 0) || (value > 15))
110 {
111 return 0;
112 }
113
114 /* Discard all DTMF tones with really low volume (<-36dbm0) */
115 if (Volume > 36)
116 {
117 return 0;
118 }
119
120 /*Are there any unended events of the same type? */
121 for (i = 0; i < DTMFdec_inst->EventBufferSize; i++)
122 {
123 /* Going through the whole queue even when we have found a match will
124 ensure that we add to the latest applicable event */
125 if ((DTMFdec_inst->EventQueue[i] == value) && (!DTMFdec_inst->EventQueueEnded[i]
126 || endEvent)) position = i;
127 }
128 if (position > -1)
129 {
130 DTMFdec_inst->EventQueueVolume[position] = Volume;
131 if ((timeStamp + Duration) > DTMFdec_inst->EventQueueEndTime[position]) DTMFdec_inst->EventQueueEndTime[position]
132 = DTMFdec_inst->EventQueueStartTime[position] + Duration;
133 if (endEvent) DTMFdec_inst->EventQueueEnded[position] = 1;
134 }
135 else
136 {
137 if (DTMFdec_inst->EventBufferSize == MAX_DTMF_QUEUE_SIZE)
138 { /* Buffer full */
139 /* Remove one event */
140 DTMFdec_inst->EventBufferSize--;
141 }
142 /* Store data in the instance on a new position*/
143 DTMFdec_inst->EventQueue[DTMFdec_inst->EventBufferSize] = value;
144 DTMFdec_inst->EventQueueVolume[DTMFdec_inst->EventBufferSize] = Volume;
145 DTMFdec_inst->EventQueueEnded[DTMFdec_inst->EventBufferSize] = endEvent;
146 DTMFdec_inst->EventQueueStartTime[DTMFdec_inst->EventBufferSize] = timeStamp;
147 DTMFdec_inst->EventQueueEndTime[DTMFdec_inst->EventBufferSize] = timeStamp
148 + Duration;
149 DTMFdec_inst->EventBufferSize++;
150 }
151 return 0;
152 }
153 return DTMF_INSERT_ERROR;
154}
155
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000156int16_t WebRtcNetEQ_DtmfDecode(dtmf_inst_t *DTMFdec_inst, int16_t *event,
157 int16_t *volume, uint32_t currTimeStamp)
niklase@google.com470e71d2011-07-07 08:21:25 +0000158{
159
160 if (DTMFdec_inst->EventBufferSize < 1) return 0; /* No events to play */
161
162 /* We have events, is it time to play them? */
163 if (currTimeStamp < DTMFdec_inst->EventQueueStartTime[0])
164 {
165 /*No, just return zero */
166 return 0;
167 }
168
169 /* Continue on the event that is currently ongoing */
170 *event = DTMFdec_inst->EventQueue[0];
171 *volume = DTMFdec_inst->EventQueueVolume[0];
172
173 if (DTMFdec_inst->EventQueueEndTime[0] >= (currTimeStamp + DTMFdec_inst->framelen))
174 {
175
176 /* Still at least framLen to play */
177
178 DTMFdec_inst->CurrentPLCtime = 0;
179 if ((DTMFdec_inst->EventQueueEndTime[0] == (currTimeStamp + DTMFdec_inst->framelen))
180 && (DTMFdec_inst->EventQueueEnded[0]))
181 { /* We are done */
182 /*Remove the event from Queue*/
183 WebRtcNetEQ_DtmfRemoveEvent(DTMFdec_inst);
184 }
185 return DTMFdec_inst->framelen;
186
187 }
188 else
189 {
190 if ((DTMFdec_inst->EventQueueEnded[0]) || (DTMFdec_inst->EventQueue[1] > -1))
191 {
192 /*
193 * Less than frameLen to play and end of event or already received next event.
194 * Give our a whole frame size of audio to simplify things.
195 */
196
197 /*Remove the event from Queue*/
198 WebRtcNetEQ_DtmfRemoveEvent(DTMFdec_inst);
199 DTMFdec_inst->CurrentPLCtime = 0;
200
201 return DTMFdec_inst->framelen;
202
203 }
204 else
205 {
206 /* Less than frameLen to play and not end of event. */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000207 DTMFdec_inst->CurrentPLCtime = (int16_t) (currTimeStamp
niklase@google.com470e71d2011-07-07 08:21:25 +0000208 - DTMFdec_inst->EventQueueEndTime[0]);
209
210 if ((DTMFdec_inst->CurrentPLCtime > DTMFdec_inst->MaxPLCtime)
211 || (DTMFdec_inst->CurrentPLCtime < -DTMFdec_inst->MaxPLCtime))
212 {
213 /*Remove the event from queue*/
214 WebRtcNetEQ_DtmfRemoveEvent(DTMFdec_inst);
215 DTMFdec_inst->CurrentPLCtime = 0;
216 }
217
218 /* If we have a new event that it's time to play */
219 if ((DTMFdec_inst->EventQueue[1] > -1) && (DTMFdec_inst->EventQueueStartTime[1]
220 >= (currTimeStamp + DTMFdec_inst->framelen)))
221 {
222 /*Remove the event from queue*/
223 WebRtcNetEQ_DtmfRemoveEvent(DTMFdec_inst);
224 DTMFdec_inst->CurrentPLCtime = 0;
225 }
226
227 return DTMFdec_inst->framelen;
228 }
229 }
230}
231
232#endif