blob: 8ea413c76f19b147c72f9f50449f26f3b7970cca [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 * This file contains the DTMF tone generator and its parameters.
13 *
14 * A sinusoid is generated using the recursive oscillator model
15 *
16 * y[n] = sin(w*n + phi) = 2*cos(w) * y[n-1] - y[n-2]
17 * = a * y[n-1] - y[n-2]
18 *
19 * initialized with
20 * y[-2] = 0
21 * y[-1] = sin(w)
22 *
23 * A DTMF signal is a combination of two sinusoids, depending
24 * on which event is sent (i.e, which key is pressed). The following
25 * table maps each key (event codes in parentheses) into two tones:
26 *
27 * 1209 Hz 1336 Hz 1477 Hz 1633 Hz
28 * 697 Hz 1 (ev. 1) 2 (ev. 2) 3 (ev. 3) A (ev. 12)
29 * 770 Hz 4 (ev. 4) 5 (ev. 5) 6 (ev. 6) B (ev. 13)
30 * 852 Hz 7 (ev. 7) 8 (ev. 8) 9 (ev. 9) C (ev. 14)
31 * 941 Hz * (ev. 10) 0 (ev. 0) # (ev. 11) D (ev. 15)
32 *
33 * The two tones are added to form the DTMF signal.
34 *
35 */
36
37#include "dtmf_tonegen.h"
38
39#include "signal_processing_library.h"
40
41#include "neteq_error_codes.h"
42
43#ifdef NETEQ_ATEVENT_DECODE
44/* Must compile NetEQ with DTMF support to enable the functionality */
45
46/*******************/
47/* Constant tables */
48/*******************/
49
50/*
51 * All tables corresponding to the oscillator model are organized so that
52 * the coefficients for a specific frequency is found in the same position
53 * in every table. The positions for the tones follow this layout:
54 *
55 * dummyVector[8] =
56 * {
57 * 697 Hz, 770 Hz, 852 Hz, 941 Hz,
58 * 1209 Hz, 1336 Hz, 1477 Hz, 1633 Hz
59 * };
60 */
61
62/*
63 * Tables for the constant a = 2*cos(w) = 2*cos(2*pi*f/fs)
64 * in the oscillator model, for 8, 16, 32 and 48 kHz sample rate.
65 * Table values in Q14.
66 */
67
pbos@webrtc.org0946a562013-04-09 00:28:06 +000068const int16_t WebRtcNetEQ_dtfm_aTbl8Khz[8] =
niklase@google.com470e71d2011-07-07 08:21:25 +000069{
70 27980, 26956, 25701, 24219,
71 19073, 16325, 13085, 9315
72};
73
74#ifdef NETEQ_WIDEBAND
pbos@webrtc.org0946a562013-04-09 00:28:06 +000075const int16_t WebRtcNetEQ_dtfm_aTbl16Khz[8]=
niklase@google.com470e71d2011-07-07 08:21:25 +000076{
77 31548, 31281, 30951, 30556,
78 29144, 28361, 27409, 26258
79};
80#endif
81
82#ifdef NETEQ_32KHZ_WIDEBAND
pbos@webrtc.org0946a562013-04-09 00:28:06 +000083const int16_t WebRtcNetEQ_dtfm_aTbl32Khz[8]=
niklase@google.com470e71d2011-07-07 08:21:25 +000084{
85 32462, 32394, 32311, 32210,
86 31849, 31647, 31400, 31098
87};
88#endif
89
90#ifdef NETEQ_48KHZ_WIDEBAND
pbos@webrtc.org0946a562013-04-09 00:28:06 +000091const int16_t WebRtcNetEQ_dtfm_aTbl48Khz[8]=
niklase@google.com470e71d2011-07-07 08:21:25 +000092{
93 32632, 32602, 32564, 32520,
94 32359, 32268, 32157, 32022
95};
96#endif
97
98/*
99 * Initialization values y[-1] = sin(w) = sin(2*pi*f/fs), for 8, 16, 32 and 48 kHz sample rate.
100 * Table values in Q14.
101 */
102
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000103const int16_t WebRtcNetEQ_dtfm_yInitTab8Khz[8] =
niklase@google.com470e71d2011-07-07 08:21:25 +0000104{
105 8528, 9315, 10163, 11036,
106 13323, 14206,15021, 15708
107};
108
109#ifdef NETEQ_WIDEBAND
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000110const int16_t WebRtcNetEQ_dtfm_yInitTab16Khz[8]=
niklase@google.com470e71d2011-07-07 08:21:25 +0000111{
112 4429, 4879, 5380, 5918,
113 7490, 8207, 8979, 9801
114};
115#endif
116
117#ifdef NETEQ_32KHZ_WIDEBAND
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000118const int16_t WebRtcNetEQ_dtfm_yInitTab32Khz[8]=
niklase@google.com470e71d2011-07-07 08:21:25 +0000119{
120 2235, 2468, 2728, 3010,
121 3853, 4249, 4685, 5164
122};
123#endif
124
125#ifdef NETEQ_48KHZ_WIDEBAND
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000126const int16_t WebRtcNetEQ_dtfm_yInitTab48Khz[8]=
niklase@google.com470e71d2011-07-07 08:21:25 +0000127{
128 1493, 1649, 1823, 2013,
129 2582, 2851, 3148, 3476
130};
131#endif
132
133/* Volume in dBm0 from 0 to -63, where 0 is the first table entry.
134 Everything below -36 is discarded, wherefore the table stops at -36.
135 Table entries are in Q14.
136 */
137
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000138const int16_t WebRtcNetEQ_dtfm_dBm0[37] = { 16141, 14386, 12821, 11427, 10184, 9077, 8090,
niklase@google.com470e71d2011-07-07 08:21:25 +0000139 7210, 6426, 5727, 5104, 4549, 4054, 3614,
140 3221, 2870, 2558, 2280, 2032, 1811, 1614,
141 1439, 1282, 1143, 1018, 908, 809, 721, 643,
142 573, 510, 455, 405, 361, 322, 287, 256 };
143
144/****************************************************************************
145 * WebRtcNetEQ_DTMFGenerate(...)
146 *
147 * Generate 10 ms DTMF signal according to input parameters.
148 *
149 * Input:
150 * - DTMFdecInst : DTMF instance
151 * - value : DTMF event number (0-15)
152 * - volume : Volume of generated signal (0-36)
153 * Volume is given in negative dBm0, i.e., volume == 0
154 * means 0 dBm0 while volume == 36 mean -36 dBm0.
155 * - sampFreq : Sample rate in Hz
156 *
157 * Output:
158 * - signal : Pointer to vector where DTMF signal is stored;
159 * Vector must be at least sampFreq/100 samples long.
160 * - DTMFdecInst : Updated DTMF instance
161 *
162 * Return value : >0 - Number of samples written to signal
163 * : <0 - error
164 */
165
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000166int16_t WebRtcNetEQ_DTMFGenerate(dtmf_tone_inst_t *DTMFdecInst, int16_t value,
167 int16_t volume, int16_t *signal,
168 uint16_t sampFreq, int16_t extFrameLen)
niklase@google.com470e71d2011-07-07 08:21:25 +0000169{
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000170 const int16_t *aTbl; /* pointer to a-coefficient table */
171 const int16_t *yInitTable; /* pointer to initialization value table */
172 int16_t a1 = 0; /* a-coefficient for first tone (low tone) */
173 int16_t a2 = 0; /* a-coefficient for second tone (high tone) */
niklase@google.com470e71d2011-07-07 08:21:25 +0000174 int i;
175 int frameLen; /* number of samples to generate */
henrik.lundin@webrtc.orgf0effa12012-09-11 12:44:06 +0000176 int lowIndex = 0; /* Default to avoid compiler warnings. */
177 int highIndex = 4; /* Default to avoid compiler warnings. */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000178 int32_t tempVal;
179 int16_t tempValLow;
180 int16_t tempValHigh;
niklase@google.com470e71d2011-07-07 08:21:25 +0000181
182 /* Sanity check for volume */
183 if ((volume < 0) || (volume > 36))
184 {
185 return DTMF_DEC_PARAMETER_ERROR;
186 }
187
188 /* Sanity check for extFrameLen */
189 if (extFrameLen < -1)
190 {
191 return DTMF_DEC_PARAMETER_ERROR;
192 }
193
194 /* Select oscillator coefficient tables based on sample rate */
195 if (sampFreq == 8000)
196 {
197 aTbl = WebRtcNetEQ_dtfm_aTbl8Khz;
198 yInitTable = WebRtcNetEQ_dtfm_yInitTab8Khz;
199 frameLen = 80;
200#ifdef NETEQ_WIDEBAND
201 }
202 else if (sampFreq == 16000)
203 {
204 aTbl = WebRtcNetEQ_dtfm_aTbl16Khz;
205 yInitTable = WebRtcNetEQ_dtfm_yInitTab16Khz;
206 frameLen = 160;
207#endif
208#ifdef NETEQ_32KHZ_WIDEBAND
209 }
210 else if (sampFreq == 32000)
211 {
212 aTbl = WebRtcNetEQ_dtfm_aTbl32Khz;
213 yInitTable = WebRtcNetEQ_dtfm_yInitTab32Khz;
214 frameLen = 320;
215#endif
216#ifdef NETEQ_48KHZ_WIDEBAND
217 }
218 else if (sampFreq == 48000)
219 {
220 aTbl = WebRtcNetEQ_dtfm_aTbl48Khz;
221 yInitTable = WebRtcNetEQ_dtfm_yInitTab48Khz;
222 frameLen = 480;
223#endif
224 }
225 else
226 {
227 /* unsupported sample rate */
228 return DTMF_GEN_UNKNOWN_SAMP_FREQ;
229 }
230
231 if (extFrameLen >= 0)
232 {
233 frameLen = extFrameLen;
234 }
235
236 /* select low frequency based on event value */
237 switch (value)
238 {
239 case 1:
240 case 2:
241 case 3:
242 case 12: /* first row on keypad */
243 {
244 lowIndex = 0; /* low frequency: 697 Hz */
245 break;
246 }
247 case 4:
248 case 5:
249 case 6:
250 case 13: /* second row on keypad */
251 {
252 lowIndex = 1; /* low frequency: 770 Hz */
253 break;
254 }
255 case 7:
256 case 8:
257 case 9:
258 case 14: /* third row on keypad */
259 {
260 lowIndex = 2; /* low frequency: 852 Hz */
261 break;
262 }
263 case 0:
264 case 10:
265 case 11:
266 case 15: /* fourth row on keypad */
267 {
268 lowIndex = 3; /* low frequency: 941 Hz */
269 break;
270 }
271 default:
272 {
273 return DTMF_DEC_PARAMETER_ERROR;
274 }
275 } /* end switch */
276
277 /* select high frequency based on event value */
278 switch (value)
279 {
280 case 1:
281 case 4:
282 case 7:
283 case 10: /* first column on keypad */
284 {
285 highIndex = 4; /* high frequency: 1209 Hz */
286 break;
287 }
288 case 2:
289 case 5:
290 case 8:
291 case 0: /* second column on keypad */
292 {
293 highIndex = 5;/* high frequency: 1336 Hz */
294 break;
295 }
296 case 3:
297 case 6:
298 case 9:
299 case 11: /* third column on keypad */
300 {
301 highIndex = 6;/* high frequency: 1477 Hz */
302 break;
303 }
304 case 12:
305 case 13:
306 case 14:
307 case 15: /* fourth column on keypad (special) */
308 {
309 highIndex = 7;/* high frequency: 1633 Hz */
310 break;
311 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000312 } /* end switch */
313
314 /* select coefficients based on results from switches above */
315 a1 = aTbl[lowIndex]; /* coefficient for first (low) tone */
316 a2 = aTbl[highIndex]; /* coefficient for second (high) tone */
317
318 if (DTMFdecInst->reinit)
319 {
320 /* set initial values for the recursive model */
321 DTMFdecInst->oldOutputLow[0] = yInitTable[lowIndex];
322 DTMFdecInst->oldOutputLow[1] = 0;
323 DTMFdecInst->oldOutputHigh[0] = yInitTable[highIndex];
324 DTMFdecInst->oldOutputHigh[1] = 0;
325
326 /* reset reinit flag */
327 DTMFdecInst->reinit = 0;
328 }
329
330 /* generate signal sample by sample */
331 for (i = 0; i < frameLen; i++)
332 {
333
334 /* Use rescursion formula y[n] = a*y[n-1] - y[n-2] */
335 tempValLow
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000336 = (int16_t) (((WEBRTC_SPL_MUL_16_16(a1, DTMFdecInst->oldOutputLow[1])
niklase@google.com470e71d2011-07-07 08:21:25 +0000337 + 8192) >> 14) - DTMFdecInst->oldOutputLow[0]);
338 tempValHigh
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000339 = (int16_t) (((WEBRTC_SPL_MUL_16_16(a2, DTMFdecInst->oldOutputHigh[1])
niklase@google.com470e71d2011-07-07 08:21:25 +0000340 + 8192) >> 14) - DTMFdecInst->oldOutputHigh[0]);
341
342 /* Update recursion memory */
343 DTMFdecInst->oldOutputLow[0] = DTMFdecInst->oldOutputLow[1];
344 DTMFdecInst->oldOutputLow[1] = tempValLow;
345 DTMFdecInst->oldOutputHigh[0] = DTMFdecInst->oldOutputHigh[1];
346 DTMFdecInst->oldOutputHigh[1] = tempValHigh;
347
348 /* scale high tone with 32768 (15 left shifts)
349 and low tone with 23171 (3dB lower than high tone) */
350 tempVal = WEBRTC_SPL_MUL_16_16(DTMF_AMP_LOW, tempValLow)
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000351 + WEBRTC_SPL_LSHIFT_W32((int32_t)tempValHigh, 15);
niklase@google.com470e71d2011-07-07 08:21:25 +0000352
353 /* Norm the signal to Q14 (with proper rounding) */
354 tempVal = (tempVal + 16384) >> 15;
355
356 /* Scale the signal to correct dbM0 value */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000357 signal[i] = (int16_t) WEBRTC_SPL_RSHIFT_W32(
niklase@google.com470e71d2011-07-07 08:21:25 +0000358 (WEBRTC_SPL_MUL_16_16(tempVal, WebRtcNetEQ_dtfm_dBm0[volume])
359 + 8192), 14); /* volume value is in Q14; use proper rounding */
360 }
361
362 return frameLen;
363
364}
365
366#endif /* NETEQ_ATEVENT_DECODE */
367