source: roaraudio/libroardsp/dtmf.c @ 5553:a17285dc6fd6

Last change on this file since 5553:a17285dc6fd6 was 5553:a17285dc6fd6, checked in by phi, 7 years ago

some random improvements to DTMF stuff

File size: 6.8 KB
Line 
1//dtmf.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2012
5 *
6 *  This file is part of libroardsp a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroardsp is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 */
24
25#include "libroardsp.h"
26
27ssize_t roar_dtmf_mus2samples(const int_least32_t t, const uint32_t rate) {
28 int64_t ret = t;
29
30 if ( t < 0 || rate == 0 ) {
31  roar_err_set(ROAR_ERROR_INVAL);
32  return -1;
33 }
34
35 ret *= (int64_t)rate;
36 ret /= (int64_t)1000000;
37
38 return ret;
39}
40
41int roar_dtmf_break(int16_t * samples, const size_t len, const uint32_t rate, const int options) {
42 (void)rate, (void)options;
43
44 ROAR_DBG("roar_dtmf_break(samples=%p, len=%llu, rate=%lu, options=%i) = ?", samples, (long long unsigned int)len, (long unsigned int)rate, options);
45
46 if ( samples == NULL ) {
47  roar_err_set(ROAR_ERROR_FAULT);
48  return -1;
49 }
50
51 memset(samples, 0, len*sizeof(int16_t));
52
53 return 0;
54}
55
56#define _FQL0 697
57#define _FQL1 770
58#define _FQL2 852
59#define _FQL3 941
60#define _FQH0 1209
61#define _FQH1 1336
62#define _FQH2 1477
63#define _FQH3 1633
64
65#define _FRL0 571
66#define _FRL1 631
67#define _FRL2 _FQL0
68#define _FRL3 _FQL1
69#define _FRL4 _FQL2
70#define _FRL5 _FQL3
71#define _FRL6 1040
72#define _FRH0 _FQH0
73#define _FRH1 _FQH1
74#define _FRH2 _FQH2
75#define _FRH3 _FQH3
76#define _FRH4 1805
77#define _FRH5 1995
78#define _FRH6 2205
79
80static const struct tone {
81 const uint16_t c;
82 const float f0;
83 const float f1;
84} _roardsp_tones[] = {
85 {ROAR_DTMF_CHAR_DTMF('1'), _FQL0, _FQH0},
86 {ROAR_DTMF_CHAR_DTMF('2'), _FQL0, _FQH1},
87 {ROAR_DTMF_CHAR_DTMF('3'), _FQL0, _FQH2},
88 {ROAR_DTMF_CHAR_DTMF('A'), _FQL0, _FQH3},
89
90 {ROAR_DTMF_CHAR_DTMF('4'), _FQL1, _FQH0},
91 {ROAR_DTMF_CHAR_DTMF('5'), _FQL1, _FQH1},
92 {ROAR_DTMF_CHAR_DTMF('6'), _FQL1, _FQH2},
93 {ROAR_DTMF_CHAR_DTMF('B'), _FQL1, _FQH3},
94
95 {ROAR_DTMF_CHAR_DTMF('7'), _FQL2, _FQH0},
96 {ROAR_DTMF_CHAR_DTMF('8'), _FQL2, _FQH1},
97 {ROAR_DTMF_CHAR_DTMF('9'), _FQL2, _FQH2},
98 {ROAR_DTMF_CHAR_DTMF('C'), _FQL2, _FQH3},
99
100 {ROAR_DTMF_CHAR_DTMF('*'), _FQL3, _FQH0},
101 {ROAR_DTMF_CHAR_DTMF('0'), _FQL3, _FQH1},
102 {ROAR_DTMF_CHAR_DTMF('#'), _FQL3, _FQH2},
103 {ROAR_DTMF_CHAR_DTMF('D'), _FQL3, _FQH3},
104
105
106 {ROAR_DTMF_CHAR_NOOP,   _FRL0, _FRH0},
107 {ROAR_DTMF_CHAR_ESCAPE, _FRL0, _FRH1},
108
109 {ROAR_DTMF_CHAR_ROAR('"'), _FRL0, _FRH2},
110 {ROAR_DTMF_CHAR_ROAR(' '), _FRL0, _FRH3},
111 {ROAR_DTMF_CHAR_ROAR('F'), _FRL0, _FRH4},
112 {ROAR_DTMF_CHAR_ROAR('M'), _FRL0, _FRH5},
113 {ROAR_DTMF_CHAR_ROAR('T'), _FRL0, _FRH6},
114 {ROAR_DTMF_CHAR_ROAR('.'), _FRL1, _FRH0},
115 {ROAR_DTMF_CHAR_ROAR('?'), _FRL1, _FRH1},
116 {ROAR_DTMF_CHAR_ROAR('!'), _FRL1, _FRH2},
117 {ROAR_DTMF_CHAR_ROAR(','), _FRL1, _FRH3},
118 {ROAR_DTMF_CHAR_ROAR('G'), _FRL1, _FRH4},
119 {ROAR_DTMF_CHAR_ROAR('N'), _FRL1, _FRH5},
120 {ROAR_DTMF_CHAR_ROAR('U'), _FRL1, _FRH6},
121 {ROAR_DTMF_CHAR_ROAR('1'), _FRL2, _FRH0},
122 {ROAR_DTMF_CHAR_ROAR('2'), _FRL2, _FRH1},
123 {ROAR_DTMF_CHAR_ROAR('3'), _FRL2, _FRH2},
124 {ROAR_DTMF_CHAR_ROAR('A'), _FRL2, _FRH3},
125 {ROAR_DTMF_CHAR_ROAR('H'), _FRL2, _FRH4},
126 {ROAR_DTMF_CHAR_ROAR('O'), _FRL2, _FRH5},
127 {ROAR_DTMF_CHAR_ROAR('V'), _FRL2, _FRH6},
128 {ROAR_DTMF_CHAR_ROAR('4'), _FRL3, _FRH0},
129 {ROAR_DTMF_CHAR_ROAR('5'), _FRL3, _FRH1},
130 {ROAR_DTMF_CHAR_ROAR('6'), _FRL3, _FRH2},
131 {ROAR_DTMF_CHAR_ROAR('B'), _FRL3, _FRH3},
132 {ROAR_DTMF_CHAR_ROAR('I'), _FRL3, _FRH4},
133 {ROAR_DTMF_CHAR_ROAR('P'), _FRL3, _FRH5},
134 {ROAR_DTMF_CHAR_ROAR('W'), _FRL3, _FRH6},
135 {ROAR_DTMF_CHAR_ROAR('7'), _FRL4, _FRH0},
136 {ROAR_DTMF_CHAR_ROAR('8'), _FRL4, _FRH1},
137 {ROAR_DTMF_CHAR_ROAR('9'), _FRL4, _FRH2},
138 {ROAR_DTMF_CHAR_ROAR('C'), _FRL4, _FRH3},
139 {ROAR_DTMF_CHAR_ROAR('J'), _FRL4, _FRH4},
140 {ROAR_DTMF_CHAR_ROAR('Q'), _FRL4, _FRH5},
141 {ROAR_DTMF_CHAR_ROAR('X'), _FRL4, _FRH6},
142 {ROAR_DTMF_CHAR_ROAR('*'), _FRL5, _FRH0},
143 {ROAR_DTMF_CHAR_ROAR('0'), _FRL5, _FRH1},
144 {ROAR_DTMF_CHAR_ROAR('#'), _FRL5, _FRH2},
145 {ROAR_DTMF_CHAR_ROAR('D'), _FRL5, _FRH3},
146 {ROAR_DTMF_CHAR_ROAR('K'), _FRL5, _FRH4},
147 {ROAR_DTMF_CHAR_ROAR('R'), _FRL5, _FRH5},
148 {ROAR_DTMF_CHAR_ROAR('Y'), _FRL5, _FRH6},
149 {ROAR_DTMF_CHAR_ROAR('@'), _FRL6, _FRH0},
150 {ROAR_DTMF_CHAR_ROAR('+'), _FRL6, _FRH1},
151 {ROAR_DTMF_CHAR_ROAR('-'), _FRL6, _FRH2},
152 {ROAR_DTMF_CHAR_ROAR('E'), _FRL6, _FRH3},
153 {ROAR_DTMF_CHAR_ROAR('L'), _FRL6, _FRH4},
154 {ROAR_DTMF_CHAR_ROAR('S'), _FRL6, _FRH5},
155 {ROAR_DTMF_CHAR_ROAR('Z'), _FRL6, _FRH6},
156
157 {0, -1, -1}
158};
159
160static const struct tone * __lookup_tone_by_char(const int options, uint16_t c) {
161 size_t i;
162
163 (void)options;
164
165 if ( (c >= ROAR_DTMF_CHAR_DTMF('a') && c <= ROAR_DTMF_CHAR_DTMF('z')) ||
166      (c >= ROAR_DTMF_CHAR_ROAR('a') && c <= ROAR_DTMF_CHAR_ROAR('z'))
167    )
168  c -= 'a' - 'A';
169
170 for (i = 0; _roardsp_tones[i].c != 0; i++) {
171  if ( _roardsp_tones[i].c == c ) {
172   return &(_roardsp_tones[i]);
173  }
174 }
175
176 roar_err_set(ROAR_ERROR_NOENT);
177 return NULL;
178}
179
180static const struct tone * __lookup_tone_by_freq(const int options, float f0, float f1) {
181 const struct tone * ct;
182 size_t i;
183 float tmp;
184
185 (void)options;
186
187 if ( f0 > f1 ) {
188  tmp = f0;
189  f0 = f1;
190  f1 = tmp;
191 }
192
193 for (i = 0; _roardsp_tones[i].c != 0; i++) {
194  ct = &(_roardsp_tones[i]);
195
196  // allow 3.5% freq error as defined in ITU-T Q.23 and Q.24.
197
198  if ( ct->f0 < f0*.965 || ct->f0 > f0*1.035 )
199   continue;
200  if ( ct->f1 < f1*.965 || ct->f1 > f1*1.035 )
201   continue;
202  return ct;
203 }
204
205 roar_err_set(ROAR_ERROR_NOENT);
206 return NULL;
207}
208
209int roar_dtmf_tone (int16_t * samples, const size_t len, const uint32_t rate, const int options, const uint16_t c) {
210 const struct tone * ct = NULL;
211 size_t i;
212 float t;
213 float t_inc = 1./rate;
214 float fc0, fc1;
215
216 ROAR_DBG("roar_dtmf_tone(samples=%p, len=%llu, rate=%lu, options=%i, c=%i) = ?", samples, (long long unsigned int)len, (long unsigned int)rate, options, (int)c);
217
218 if ( samples == NULL ) {
219  roar_err_set(ROAR_ERROR_FAULT);
220  return -1;
221 }
222
223 if ( c == ROAR_DTMF_CHAR_BREAK )
224  return roar_dtmf_break(samples, len, rate, options);
225
226 ct = __lookup_tone_by_char(options, c);
227
228 if ( ct == NULL ) {
229  roar_err_set(ROAR_ERROR_NOENT);
230  return -1;
231 }
232
233 fc0 = 2. * M_PI * ct->f0;
234 fc1 = 2. * M_PI * ct->f1;
235
236// memset(samples, 0, len);
237
238 for (i = 0, t = 0.; i < len; t += t_inc, i++) {
239  samples[i] = (sinf(fc0*t) + sinf(fc1*t))*8192.0;
240 }
241
242 return 0;
243}
244
245uint16_t roar_dtmf_freqs2char(const int options, float f0, float f1) {
246 const struct tone * ct = __lookup_tone_by_freq(options, f0, f1);
247
248 if ( ct == NULL )
249  return ROAR_DTMF_CHAR_BREAK;
250 return ct->c;
251}
252
253//ll
Note: See TracBrowser for help on using the repository browser.