1 /*
2 * Copyright (c) 2012 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 #include "webrtc/voice_engine/dtmf_inband.h"
12
13 #include <assert.h>
14
15 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
16 #include "webrtc/system_wrappers/interface/trace.h"
17
18 namespace webrtc {
19
20 const int16_t Dtmf_a_times2Tab8Khz[8]=
21 {
22 27978, 26956, 25701, 24219,
23 19073, 16325, 13085, 9314
24 };
25
26 const int16_t Dtmf_a_times2Tab16Khz[8]=
27 {
28 31548, 31281, 30951, 30556,
29 29144, 28361, 27409, 26258
30 };
31
32 const int16_t Dtmf_a_times2Tab32Khz[8]=
33 {
34 32462,32394, 32311, 32210, 31849, 31647, 31400, 31098
35 };
36
37 const int16_t Dtmf_a_times2Tab44_1Khz[8]=
38 {
39 32607, 32571, 32527, 32474, 32283, 32176, 32045, 31885
40 };
41
42 const int16_t Dtmf_a_times2Tab48Khz[8]=
43 {
44 32612, 32577, 32534, 32483, 32298, 32194, 32067, 31912
45 };
46
47 // Second table is sin(2*pi*f/fs) in Q14
48
49 const int16_t Dtmf_ym2Tab8Khz[8]=
50 {
51 8527, 9315, 10163, 11036,
52 13322, 14206, 15021, 15708
53 };
54
55 const int16_t Dtmf_ym2Tab16Khz[8]=
56 {
57 4429, 4879, 5380, 5918,
58 7490, 8207, 8979, 9801
59 };
60
61 const int16_t Dtmf_ym2Tab32Khz[8]=
62 {
63 2235, 2468, 2728, 3010, 3853, 4249, 4685, 5164
64 };
65
66 const int16_t Dtmf_ym2Tab44_1Khz[8]=
67 {
68 1624, 1794, 1984, 2190, 2808, 3100, 3422, 3777
69 };
70
71 const int16_t Dtmf_ym2Tab48Khz[8]=
72 {
73 1599, 1766, 1953, 2156, 2765, 3052, 3369, 3719
74 };
75
76 const int16_t Dtmf_dBm0kHz[37]=
77 {
78 16141, 14386, 12821, 11427, 10184, 9077,
79 8090, 7210, 6426, 5727, 5104, 4549,
80 4054, 3614, 3221, 2870, 2558, 2280,
81 2032, 1811, 1614, 1439, 1282, 1143,
82 1018, 908, 809, 721, 643, 573,
83 510, 455, 405, 361, 322, 287,
84 256
85 };
86
87
DtmfInband(int32_t id)88 DtmfInband::DtmfInband(int32_t id) :
89 _critSect(*CriticalSectionWrapper::CreateCriticalSection()),
90 _id(id),
91 _outputFrequencyHz(8000),
92 _frameLengthSamples(0),
93 _remainingSamples(0),
94 _eventCode(0),
95 _attenuationDb(0),
96 _lengthMs(0),
97 _reinit(true),
98 _playing(false),
99 _delaySinceLastToneMS(1000)
100 {
101 memset(_oldOutputLow, 0, sizeof(_oldOutputLow));
102 memset(_oldOutputHigh, 0, sizeof(_oldOutputHigh));
103 }
104
~DtmfInband()105 DtmfInband::~DtmfInband()
106 {
107 delete &_critSect;
108 }
109
110 int
SetSampleRate(uint16_t frequency)111 DtmfInband::SetSampleRate(uint16_t frequency)
112 {
113 if (frequency != 8000 &&
114 frequency != 16000 &&
115 frequency != 32000 &&
116 frequency != 44100 &&
117 frequency != 48000)
118 {
119 // invalid sample rate
120 assert(false);
121 return -1;
122 }
123 _outputFrequencyHz = frequency;
124 return 0;
125 }
126
127 int
GetSampleRate(uint16_t & frequency)128 DtmfInband::GetSampleRate(uint16_t& frequency)
129 {
130 frequency = _outputFrequencyHz;
131 return 0;
132 }
133
134 void
Init()135 DtmfInband::Init()
136 {
137 _remainingSamples = 0;
138 _frameLengthSamples = 0;
139 _eventCode = 0;
140 _attenuationDb = 0;
141 _lengthMs = 0;
142 _reinit = true;
143 _oldOutputLow[0] = 0;
144 _oldOutputLow[1] = 0;
145 _oldOutputHigh[0] = 0;
146 _oldOutputHigh[1] = 0;
147 _delaySinceLastToneMS = 1000;
148 }
149
150 int
AddTone(uint8_t eventCode,int32_t lengthMs,int32_t attenuationDb)151 DtmfInband::AddTone(uint8_t eventCode,
152 int32_t lengthMs,
153 int32_t attenuationDb)
154 {
155 CriticalSectionScoped lock(&_critSect);
156
157 if (attenuationDb > 36 || eventCode > 15)
158 {
159 assert(false);
160 return -1;
161 }
162
163 if (IsAddingTone())
164 {
165 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_id,-1),
166 "DtmfInband::AddTone() new tone interrupts ongoing tone");
167 }
168
169 ReInit();
170
171 _frameLengthSamples = static_cast<int16_t> (_outputFrequencyHz / 100);
172 _eventCode = static_cast<int16_t> (eventCode);
173 _attenuationDb = static_cast<int16_t> (attenuationDb);
174 _remainingSamples = static_cast<int32_t>
175 (lengthMs * (_outputFrequencyHz / 1000));
176 _lengthMs = lengthMs;
177
178 return 0;
179 }
180
181 int
ResetTone()182 DtmfInband::ResetTone()
183 {
184 CriticalSectionScoped lock(&_critSect);
185
186 ReInit();
187
188 _frameLengthSamples = static_cast<int16_t> (_outputFrequencyHz / 100);
189 _remainingSamples = static_cast<int32_t>
190 (_lengthMs * (_outputFrequencyHz / 1000));
191
192 return 0;
193 }
194
195 int
StartTone(uint8_t eventCode,int32_t attenuationDb)196 DtmfInband::StartTone(uint8_t eventCode,
197 int32_t attenuationDb)
198 {
199 CriticalSectionScoped lock(&_critSect);
200
201 if (attenuationDb > 36 || eventCode > 15)
202 {
203 assert(false);
204 return -1;
205 }
206
207 if (IsAddingTone())
208 {
209 return -1;
210 }
211
212 ReInit();
213
214 _frameLengthSamples = static_cast<int16_t> (_outputFrequencyHz / 100);
215 _eventCode = static_cast<int16_t> (eventCode);
216 _attenuationDb = static_cast<int16_t> (attenuationDb);
217 _playing = true;
218
219 return 0;
220 }
221
222 int
StopTone()223 DtmfInband::StopTone()
224 {
225 CriticalSectionScoped lock(&_critSect);
226
227 if (!_playing)
228 {
229 return 0;
230 }
231
232 _playing = false;
233
234 return 0;
235 }
236
237 // Shall be called between tones
238 void
ReInit()239 DtmfInband::ReInit()
240 {
241 _reinit = true;
242 }
243
244 bool
IsAddingTone()245 DtmfInband::IsAddingTone()
246 {
247 CriticalSectionScoped lock(&_critSect);
248 return (_remainingSamples > 0 || _playing);
249 }
250
251 int
Get10msTone(int16_t output[MAX_DTMF_SAMPLERATE/100],uint16_t & outputSizeInSamples)252 DtmfInband::Get10msTone(int16_t output[MAX_DTMF_SAMPLERATE/100],
253 uint16_t& outputSizeInSamples)
254 {
255 CriticalSectionScoped lock(&_critSect);
256 if (DtmfFix_generate(output,
257 _eventCode,
258 _attenuationDb,
259 _frameLengthSamples,
260 _outputFrequencyHz) == -1)
261 {
262 return -1;
263 }
264 _remainingSamples -= _frameLengthSamples;
265 outputSizeInSamples = _frameLengthSamples;
266 _delaySinceLastToneMS = 0;
267 return 0;
268 }
269
270 void
UpdateDelaySinceLastTone()271 DtmfInband::UpdateDelaySinceLastTone()
272 {
273 _delaySinceLastToneMS += kDtmfFrameSizeMs;
274 // avoid wraparound
275 if (_delaySinceLastToneMS > (1<<30))
276 {
277 _delaySinceLastToneMS = 1000;
278 }
279 }
280
281 uint32_t
DelaySinceLastTone() const282 DtmfInband::DelaySinceLastTone() const
283 {
284 return _delaySinceLastToneMS;
285 }
286
287 int16_t
DtmfFix_generate(int16_t * decoded,int16_t value,int16_t volume,int16_t frameLen,uint16_t fs)288 DtmfInband::DtmfFix_generate(int16_t *decoded,
289 int16_t value,
290 int16_t volume,
291 int16_t frameLen,
292 uint16_t fs)
293 {
294 const int16_t *a_times2Tbl;
295 const int16_t *y2_Table;
296 int16_t a1_times2 = 0, a2_times2 = 0;
297
298 if (fs==8000) {
299 a_times2Tbl=Dtmf_a_times2Tab8Khz;
300 y2_Table=Dtmf_ym2Tab8Khz;
301 } else if (fs==16000) {
302 a_times2Tbl=Dtmf_a_times2Tab16Khz;
303 y2_Table=Dtmf_ym2Tab16Khz;
304 } else if (fs==32000) {
305 a_times2Tbl=Dtmf_a_times2Tab32Khz;
306 y2_Table=Dtmf_ym2Tab32Khz;
307 } else if (fs==44100) {
308 a_times2Tbl=Dtmf_a_times2Tab44_1Khz;
309 y2_Table=Dtmf_ym2Tab44_1Khz;
310 } else if (fs==48000) {
311 a_times2Tbl=Dtmf_a_times2Tab48Khz;
312 y2_Table=Dtmf_ym2Tab48Khz;
313 } else {
314 return(-1);
315 }
316
317 if ((value==1)||(value==2)||(value==3)||(value==12)) {
318 a1_times2=a_times2Tbl[0];
319 if (_reinit) {
320 _oldOutputLow[0]=y2_Table[0];
321 _oldOutputLow[1]=0;
322 }
323 } else if ((value==4)||(value==5)||(value==6)||(value==13)) {
324 a1_times2=a_times2Tbl[1];
325 if (_reinit) {
326 _oldOutputLow[0]=y2_Table[1];
327 _oldOutputLow[1]=0;
328 }
329 } else if ((value==7)||(value==8)||(value==9)||(value==14)) {
330 a1_times2=a_times2Tbl[2];
331 if (_reinit) {
332 _oldOutputLow[0]=y2_Table[2];
333 _oldOutputLow[1]=0;
334 }
335 } else if ((value==10)||(value==0)||(value==11)||(value==15)) {
336 a1_times2=a_times2Tbl[3];
337 if (_reinit) {
338 _oldOutputLow[0]=y2_Table[3];
339 _oldOutputLow[1]=0;
340 }
341 }
342 if ((value==1)||(value==4)||(value==7)||(value==10)) {
343 a2_times2=a_times2Tbl[4];
344 if (_reinit) {
345 _oldOutputHigh[0]=y2_Table[4];
346 _oldOutputHigh[1]=0;
347 _reinit=false;
348 }
349 } else if ((value==2)||(value==5)||(value==8)||(value==0)) {
350 a2_times2=a_times2Tbl[5];
351 if (_reinit) {
352 _oldOutputHigh[0]=y2_Table[5];
353 _oldOutputHigh[1]=0;
354 _reinit=false;
355 }
356 } else if ((value==3)||(value==6)||(value==9)||(value==11)) {
357 a2_times2=a_times2Tbl[6];
358 if (_reinit) {
359 _oldOutputHigh[0]=y2_Table[6];
360 _oldOutputHigh[1]=0;
361 _reinit=false;
362 }
363 } else if ((value==12)||(value==13)||(value==14)||(value==15)) {
364 a2_times2=a_times2Tbl[7];
365 if (_reinit) {
366 _oldOutputHigh[0]=y2_Table[7];
367 _oldOutputHigh[1]=0;
368 _reinit=false;
369 }
370 }
371
372 return (DtmfFix_generateSignal(a1_times2,
373 a2_times2,
374 volume,
375 decoded,
376 frameLen));
377 }
378
379 int16_t
DtmfFix_generateSignal(int16_t a1_times2,int16_t a2_times2,int16_t volume,int16_t * signal,int16_t length)380 DtmfInband::DtmfFix_generateSignal(int16_t a1_times2,
381 int16_t a2_times2,
382 int16_t volume,
383 int16_t *signal,
384 int16_t length)
385 {
386 int i;
387
388 /* Generate Signal */
389 for (i=0;i<length;i++) {
390 int32_t tempVal;
391 int16_t tempValLow, tempValHigh;
392
393 /* Use recursion formula y[n] = a*2*y[n-1] - y[n-2] */
394 tempValLow = (int16_t)(((( (int32_t)(a1_times2 *
395 _oldOutputLow[1])) + 8192) >> 14) - _oldOutputLow[0]);
396 tempValHigh = (int16_t)(((( (int32_t)(a2_times2 *
397 _oldOutputHigh[1])) + 8192) >> 14) - _oldOutputHigh[0]);
398
399 /* Update memory */
400 _oldOutputLow[0]=_oldOutputLow[1];
401 _oldOutputLow[1]=tempValLow;
402 _oldOutputHigh[0]=_oldOutputHigh[1];
403 _oldOutputHigh[1]=tempValHigh;
404
405 tempVal = (int32_t)(kDtmfAmpLow * tempValLow) +
406 (int32_t)(kDtmfAmpHigh * tempValHigh);
407
408 /* Norm the signal to Q14 */
409 tempVal=(tempVal+16384)>>15;
410
411 /* Scale the signal to correct dbM0 value */
412 signal[i]=(int16_t)((tempVal*Dtmf_dBm0kHz[volume]+8192)>>14);
413 }
414
415 return(0);
416 }
417
418 } // namespace webrtc
419