1 /*
2 * ----------------------------------------------------------------------------
3 * "THE BEER-WARE LICENSE" (Revision 42):
4 * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you
5 * can do whatever you want with this stuff. If we meet some day, and you think
6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
7 * ----------------------------------------------------------------------------
8 *
9 * Extract DTMF signals from 16 bit PCM audio
10 *
11 * Originally written by Poul-Henning Kamp <phk@freebsd.org>
12 * Made into a C++ class by Roger Hardiman <roger@freebsd.org>, January 2002
13 *
14 * $Revision: 23725 $
15 * $Author: rjongbloed $
16 * $Date: 2009-10-28 22:11:42 -0500 (Wed, 28 Oct 2009) $
17 */
18
19 #ifdef __GNUC__
20 #pragma implementation "dtmf.h"
21 #endif
22
23 #include <ptlib.h>
24 #include <ptclib/dtmf.h>
25
26 #if P_DTMF
27
28 #include <math.h>
29
30 /* Integer math scaling factor */
31 #define FSC (1<<12)
32
33 /* This is the Q of the filter (pole radius) */
34 #define POLRAD .99
35
36 #define P2 ((int)(POLRAD*POLRAD*FSC))
37
PDTMFDecoder()38 PDTMFDecoder::PDTMFDecoder()
39 : sampleCount(0)
40 , tonesDetected(0)
41 , inputAmplitude(0)
42 {
43 // Initialise the class
44 int i;
45 for (i = 0; i < NumTones; i++)
46 y[i] = h[i] = k[i] = 0;
47
48 for (i = 0; i < 256; i++)
49 key[i] = '?';
50
51 /* We encode the tones in 8 bits, translate those to symbol */
52 key[0x11] = '1'; key[0x12] = '4'; key[0x14] = '7'; key[0x18] = '*';
53 key[0x21] = '2'; key[0x22] = '5'; key[0x24] = '8'; key[0x28] = '0';
54 key[0x41] = '3'; key[0x42] = '6'; key[0x44] = '9'; key[0x48] = '#';
55 key[0x81] = 'A'; key[0x82] = 'B'; key[0x84] = 'C'; key[0x88] = 'D';
56
57 /* The frequencies we're trying to detect */
58 /* These are precalculated to save processing power */
59 /* static int dtmf[9] = {697, 770, 852, 941, 1209, 1336, 1477, 1633, 1100, 2100}; */
60 /* p1[tone] = (-cos(2 * 3.141592 * dtmf[tone] / 8000.0) * FSC) */
61 p1[0] = -3497; p1[1] = -3369; p1[2] = -3212; p1[3] = -3027;
62 p1[4] = -2384; p1[5] = -2040; p1[6] = -1635; p1[7] = -1164;
63 p1[8] = -2660; p1[9] = 321;
64 }
65
Decode(const short * sampleData,PINDEX numSamples,unsigned mult,unsigned div)66 PString PDTMFDecoder::Decode(const short * sampleData, PINDEX numSamples, unsigned mult, unsigned div)
67 {
68 #if 0
69 {
70 static int fd = -1;
71 if (fd < 0) {
72 fd = ::_open("dtmf.pcm", _O_BINARY | _O_CREAT | O_RDWR, 0777);
73 PTRACE(1, "DTMF\tdebug file opened");
74 }
75 if (fd >= 0)
76 ::_write(fd, sampleData, numSamples*2);
77 }
78 #endif
79
80 PString keyString;
81
82 PINDEX pos;
83 for (pos = 0; pos < numSamples; pos++) {
84
85 /* Read (and scale) the next 16 bit sample */
86 int x = (int)(mult * (*sampleData++)) / div;
87 x = x / (32768/FSC);
88
89 /* Input amplitude */
90 if (x > 0)
91 inputAmplitude += (x - inputAmplitude) / 128;
92 else
93 inputAmplitude += (-x - inputAmplitude) / 128;
94
95 /* For each tone */
96 int newTones = 0;
97 for (int tone = 0; tone < NumTones; tone++) {
98
99 /* Turn the crank */
100 int c = (P2 * (x - k[tone])) / FSC;
101 int d = x + c;
102 int f = (p1[tone] * (d - h[tone])) / FSC;
103 int n = x - k[tone] - c;
104 k[tone] = h[tone] + f;
105 h[tone] = f + d;
106
107 /* Detect and Average */
108 if (n > 0)
109 y[tone] += (n - y[tone]) / 64;
110 else
111 y[tone] += (-n - y[tone]) / 64;
112
113 /* Threshold */
114 if (y[tone] > FSC/10 && y[tone] > inputAmplitude)
115 newTones |= 1 << tone;
116 }
117
118 /* Hysteresis and noise supressor */
119 if (newTones != tonesDetected) {
120 sampleCount = 0;
121 tonesDetected = newTones;
122 }
123 else if (sampleCount++ == DetectSamples) {
124 if (tonesDetected < 256) {
125 if (key[tonesDetected] != '?') {
126 PTRACE(3,"DTMF\tDetected '" << key[tonesDetected] << "' in PCM-16 stream");
127 keyString += key[tonesDetected];
128 }
129 }
130 else {
131 char ch = 0;
132 if ((tonesDetected & 0x100) != 0)
133 ch = 'X';
134 else if ((tonesDetected & 0x200) != 0)
135 ch = 'Y';
136
137 if (ch != 0) {
138 PTRACE(3,"DTMF\tDetected tone '" << ch << "' in PCM-16 stream");
139 keyString += ch;
140 }
141 }
142 }
143 }
144 return keyString;
145 }
146
147 ////////////////////////////////////////////////////////////////////////////////////////////
148
sine(int angle,int freq)149 static int sine(int angle, int freq)
150 {
151 static int const sinArray[2000] = {
152 0,0,1,2,3,3,4,5,6,7,7,8,9,10,10,11,12,13,14,14,15,16,17,18,18,19,20,21,21,22,
153 23,24,25,25,26,27,28,29,29,30,31,32,32,33,34,35,36,36,37,38,39,40,40,41,42,43,43,44,45,46,
154 47,47,48,49,50,51,51,52,53,54,54,55,56,57,58,58,59,60,61,62,62,63,64,65,65,66,67,68,69,69,
155 70,71,72,72,73,74,75,76,76,77,78,79,80,80,81,82,83,83,84,85,86,87,87,88,89,90,90,91,92,93,
156 94,94,95,96,97,98,98,99,100,101,101,102,103,104,105,105,106,107,108,108,109,110,111,112,112,113,114,115,115,116,
157 117,118,119,119,120,121,122,122,123,124,125,126,126,127,128,129,130,130,131,132,133,133,134,135,136,137,137,138,139,140,
158 140,141,142,143,144,144,145,146,147,147,148,149,150,151,151,152,153,154,154,155,156,157,157,158,159,160,161,161,162,163,
159 164,164,165,166,167,168,168,169,170,171,171,172,173,174,175,175,176,177,178,178,179,180,181,181,182,183,184,185,185,186,
160 187,188,188,189,190,191,192,192,193,194,195,195,196,197,198,198,199,200,201,202,202,203,204,205,205,206,207,208,208,209,
161 210,211,212,212,213,214,215,215,216,217,218,218,219,220,221,221,222,223,224,225,225,226,227,228,228,229,230,231,231,232,
162 233,234,234,235,236,237,238,238,239,240,241,241,242,243,244,244,245,246,247,247,248,249,250,250,251,252,253,254,254,255,
163 256,257,257,258,259,260,260,261,262,263,263,264,265,266,266,267,268,269,269,270,271,272,272,273,274,275,275,276,277,278,
164 278,279,280,281,282,282,283,284,285,285,286,287,288,288,289,290,291,291,292,293,294,294,295,296,297,297,298,299,300,300,
165 301,302,303,303,304,305,306,306,307,308,309,309,310,311,312,312,313,314,314,315,316,317,317,318,319,320,320,321,322,323,
166 323,324,325,326,326,327,328,329,329,330,331,332,332,333,334,335,335,336,337,337,338,339,340,340,341,342,343,343,344,345,
167 346,346,347,348,349,349,350,351,352,352,353,354,354,355,356,357,357,358,359,360,360,361,362,363,363,364,365,365,366,367,
168 368,368,369,370,371,371,372,373,373,374,375,376,376,377,378,379,379,380,381,381,382,383,384,384,385,386,387,387,388,389,
169 389,390,391,392,392,393,394,394,395,396,397,397,398,399,400,400,401,402,402,403,404,405,405,406,407,407,408,409,410,410,
170 411,412,412,413,414,415,415,416,417,417,418,419,420,420,421,422,422,423,424,425,425,426,427,427,428,429,430,430,431,432,
171 432,433,434,434,435,436,437,437,438,439,439,440,441,442,442,443,444,444,445,446,446,447,448,449,449,450,451,451,452,453,
172 453,454,455,456,456,457,458,458,459,460,460,461,462,463,463,464,465,465,466,467,467,468,469,470,470,471,472,472,473,474,
173 474,475,476,476,477,478,478,479,480,481,481,482,483,483,484,485,485,486,487,487,488,489,489,490,491,492,492,493,494,494,
174 495,496,496,497,498,498,499,500,500,501,502,502,503,504,504,505,506,507,507,508,509,509,510,511,511,512,513,513,514,515,
175 515,516,517,517,518,519,519,520,521,521,522,523,523,524,525,525,526,527,527,528,529,529,530,531,531,532,533,533,534,535,
176 535,536,537,537,538,539,539,540,541,541,542,543,543,544,545,545,546,547,547,548,549,549,550,550,551,552,552,553,554,554,
177 555,556,556,557,558,558,559,560,560,561,562,562,563,564,564,565,565,566,567,567,568,569,569,570,571,571,572,573,573,574,
178 575,575,576,576,577,578,578,579,580,580,581,582,582,583,583,584,585,585,586,587,587,588,589,589,590,590,591,592,592,593,
179 594,594,595,596,596,597,597,598,599,599,600,601,601,602,602,603,604,604,605,606,606,607,607,608,609,609,610,611,611,612,
180 612,613,614,614,615,616,616,617,617,618,619,619,620,620,621,622,622,623,624,624,625,625,626,627,627,628,628,629,630,630,
181 631,631,632,633,633,634,635,635,636,636,637,638,638,639,639,640,641,641,642,642,643,644,644,645,645,646,647,647,648,648,
182 649,650,650,651,651,652,653,653,654,654,655,655,656,657,657,658,658,659,660,660,661,661,662,663,663,664,664,665,666,666,
183 667,667,668,668,669,670,670,671,671,672,673,673,674,674,675,675,676,677,677,678,678,679,679,680,681,681,682,682,683,683,
184 684,685,685,686,686,687,687,688,689,689,690,690,691,691,692,693,693,694,694,695,695,696,697,697,698,698,699,699,700,700,
185 701,702,702,703,703,704,704,705,705,706,707,707,708,708,709,709,710,710,711,712,712,713,713,714,714,715,715,716,717,717,
186 718,718,719,719,720,720,721,721,722,723,723,724,724,725,725,726,726,727,727,728,728,729,730,730,731,731,732,732,733,733,
187 734,734,735,735,736,736,737,738,738,739,739,740,740,741,741,742,742,743,743,744,744,745,745,746,746,747,748,748,749,749,
188 750,750,751,751,752,752,753,753,754,754,755,755,756,756,757,757,758,758,759,759,760,760,761,761,762,762,763,763,764,764,
189 765,765,766,766,767,768,768,769,769,770,770,771,771,772,772,773,773,774,774,774,775,775,776,776,777,777,778,778,779,779,
190 780,780,781,781,782,782,783,783,784,784,785,785,786,786,787,787,788,788,789,789,790,790,791,791,792,792,793,793,793,794,
191 794,795,795,796,796,797,797,798,798,799,799,800,800,801,801,802,802,802,803,803,804,804,805,805,806,806,807,807,808,808,
192 809,809,809,810,810,811,811,812,812,813,813,814,814,814,815,815,816,816,817,817,818,818,819,819,819,820,820,821,821,822,
193 822,823,823,823,824,824,825,825,826,826,827,827,827,828,828,829,829,830,830,831,831,831,832,832,833,833,834,834,834,835,
194 835,836,836,837,837,837,838,838,839,839,840,840,840,841,841,842,842,843,843,843,844,844,845,845,846,846,846,847,847,848,
195 848,848,849,849,850,850,850,851,851,852,852,853,853,853,854,854,855,855,855,856,856,857,857,857,858,858,859,859,859,860,
196 860,861,861,861,862,862,863,863,863,864,864,865,865,865,866,866,867,867,867,868,868,869,869,869,870,870,870,871,871,872,
197 872,872,873,873,874,874,874,875,875,875,876,876,877,877,877,878,878,878,879,879,880,880,880,881,881,881,882,882,883,883,
198 883,884,884,884,885,885,885,886,886,887,887,887,888,888,888,889,889,889,890,890,891,891,891,892,892,892,893,893,893,894,
199 894,894,895,895,895,896,896,896,897,897,898,898,898,899,899,899,900,900,900,901,901,901,902,902,902,903,903,903,904,904,
200 904,905,905,905,906,906,906,907,907,907,908,908,908,909,909,909,910,910,910,911,911,911,912,912,912,913,913,913,913,914,
201 914,914,915,915,915,916,916,916,917,917,917,918,918,918,918,919,919,919,920,920,920,921,921,921,922,922,922,922,923,923,
202 923,924,924,924,925,925,925,925,926,926,926,927,927,927,928,928,928,928,929,929,929,930,930,930,930,931,931,931,932,932,
203 932,932,933,933,933,934,934,934,934,935,935,935,935,936,936,936,937,937,937,937,938,938,938,939,939,939,939,940,940,940,
204 940,941,941,941,941,942,942,942,942,943,943,943,944,944,944,944,945,945,945,945,946,946,946,946,947,947,947,947,948,948,
205 948,948,949,949,949,949,950,950,950,950,951,951,951,951,952,952,952,952,952,953,953,953,953,954,954,954,954,955,955,955,
206 955,956,956,956,956,956,957,957,957,957,958,958,958,958,958,959,959,959,959,960,960,960,960,960,961,961,961,961,962,962,
207 962,962,962,963,963,963,963,963,964,964,964,964,964,965,965,965,965,965,966,966,966,966,967,967,967,967,967,967,968,968,
208 968,968,968,969,969,969,969,969,970,970,970,970,970,971,971,971,971,971,972,972,972,972,972,972,973,973,973,973,973,973,
209 974,974,974,974,974,975,975,975,975,975,975,976,976,976,976,976,976,977,977,977,977,977,977,978,978,978,978,978,978,979,
210 979,979,979,979,979,980,980,980,980,980,980,980,981,981,981,981,981,981,981,982,982,982,982,982,982,983,983,983,983,983,
211 983,983,984,984,984,984,984,984,984,984,985,985,985,985,985,985,985,986,986,986,986,986,986,986,986,987,987,987,987,987,
212 987,987,987,988,988,988,988,988,988,988,988,989,989,989,989,989,989,989,989,989,990,990,990,990,990,990,990,990,990,990,
213 991,991,991,991,991,991,991,991,991,992,992,992,992,992,992,992,992,992,992,992,993,993,993,993,993,993,993,993,993,993,
214 993,994,994,994,994,994,994,994,994,994,994,994,994,995,995,995,995,995,995,995,995,995,995,995,995,995,995,996,996,996,
215 996,996,996,996,996,996,996,996,996,996,996,996,997,997,997,997,997,997,997,997,997,997,997,997,997,997,997,997,997,997,
216 998,998,998,998,998,998,998,998,998,998,998,998,998,998,998,998,998,998,998,998,998,998,998,998,999,999,999,999,999,999,
217 999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,
218 999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999
219 };
220 static int const sinArraySize = sizeof(sinArray)/sizeof(sinArray[0]);
221
222 int adjustedAngle = (int)(angle*sinArraySize*4LL/freq);
223 int quadrant = adjustedAngle / sinArraySize;
224 int offset = adjustedAngle % sinArraySize;
225
226 switch (quadrant) {
227 case 0:
228 return sinArray[offset];
229 case 1:
230 return sinArray[sinArraySize-1-offset];
231 case 2:
232 return -sinArray[offset];
233 default:
234 return -sinArray[sinArraySize-1-offset];
235 }
236 }
237
238
239 ////////////////////////////////////////////////////////////////////////
240
241
PTones(unsigned volume,unsigned sampleRate)242 PTones::PTones(unsigned volume, unsigned sampleRate)
243 : m_sampleRate(sampleRate)
244 , m_masterVolume(volume)
245 {
246 Construct();
247 }
248
249
PTones(const PString & descriptor,unsigned volume,unsigned sampleRate)250 PTones::PTones(const PString & descriptor, unsigned volume, unsigned sampleRate)
251 : m_sampleRate(sampleRate)
252 , m_masterVolume(volume)
253 {
254 Construct();
255
256 if (!Generate(descriptor)) {
257 PTRACE(1,"DTMF\tCannot encode tone \"" << descriptor << '"');
258 }
259 }
260
261
Construct()262 void PTones::Construct()
263 {
264 m_lastOperation = 0;
265 m_lastFrequency1 = 0;
266 m_lastFrequency2 = 0;
267 m_angle1 = 0;
268 m_angle2 = 0;
269
270 if (m_sampleRate < 8000)
271 m_sampleRate = 8000;
272 else if (m_sampleRate > 96000)
273 m_sampleRate = 96000;
274
275 m_maxFrequency = m_sampleRate/4;
276
277 if (m_masterVolume < 1)
278 m_masterVolume = 1;
279 else if (m_masterVolume > 100)
280 m_masterVolume = 100;
281 }
282
283
Generate(const PString & descriptor)284 bool PTones::Generate(const PString & descriptor)
285 {
286 PStringArray toneChunks = descriptor.Tokenise('/');
287 if (toneChunks.IsEmpty())
288 return false;
289
290 for (PINDEX chunk = 0; chunk < toneChunks.GetSize(); chunk++) {
291 // split frequency and cadence
292 PINDEX pos = toneChunks[chunk].Find(':');
293 if (pos == P_MAX_INDEX)
294 return false;
295
296 PString frequencyStr = toneChunks[chunk].Left(pos).Trim();
297 PString cadenceStr = toneChunks[chunk].Mid(pos+1).Trim();
298
299 if (cadenceStr.IsEmpty())
300 return false;
301
302 // Do we have a volume?
303 unsigned volume = 100;
304 if ((pos = frequencyStr.Find('%')) != P_MAX_INDEX) {
305 volume = frequencyStr.Left(pos).AsUnsigned();
306 if (volume < 1 || volume > 100)
307 return false;
308 frequencyStr.Delete(0, pos+1);
309 }
310
311 if (frequencyStr.IsEmpty())
312 return false;
313
314 // Parse the frequencies
315 unsigned frequency1, frequency2;
316 char operation;
317 if ((pos = frequencyStr.FindOneOf("+-x")) != P_MAX_INDEX) {
318 frequency1 = frequencyStr.Left(pos).AsUnsigned();
319 frequency2 = frequencyStr.Mid(pos+1).AsUnsigned();
320 operation = frequencyStr[pos];
321 }
322 else {
323 frequency1 = frequency2 = frequencyStr.AsUnsigned();
324 operation = '-';
325 }
326
327 // Parse the cadence
328 double duration = cadenceStr.AsReal();
329
330 // First one
331 if (!Generate(operation, frequency1, frequency2, (unsigned)(duration*1000), volume))
332 return false;
333
334 char originalOperation = operation;
335 operation = ' ';
336
337 pos = 0;
338 while ((pos = cadenceStr.Find('-', pos)) != P_MAX_INDEX) {
339 duration = cadenceStr.Mid(++pos).AsReal();
340 if (duration < 0 || duration > 60)
341 return false;
342
343 if (!Generate(operation, frequency1, frequency2, (unsigned)(duration*1000), volume))
344 return false;
345
346 // Alternate between the tone and silence
347 operation = operation == ' ' ? originalOperation : ' ';
348 }
349 }
350
351 return true;
352 }
353
354
Generate(char operation,unsigned frequency1,unsigned frequency2,unsigned milliseconds,unsigned volume)355 bool PTones::Generate(char operation, unsigned frequency1, unsigned frequency2, unsigned milliseconds, unsigned volume)
356 {
357 if (m_lastOperation != operation ||
358 m_lastFrequency1 != frequency1 ||
359 m_lastFrequency2 != frequency2) {
360 m_lastOperation = operation;
361 m_lastFrequency1 = frequency1;
362 m_lastFrequency2 = frequency2;
363
364 m_angle1 = 0;
365 m_angle2 = 0;
366 }
367
368 switch (operation) {
369 case '+':
370 return Juxtapose(frequency1, frequency2, milliseconds, volume);
371
372 case 'x':
373 return Modulate(frequency1, frequency2, milliseconds, volume);
374
375 case '-':
376 return PureTone(frequency1, milliseconds, volume);
377
378 case ' ':
379 return Silence(milliseconds);
380 }
381
382 return false;
383 }
384
385
Juxtapose(unsigned frequency1,unsigned frequency2,unsigned milliseconds,unsigned volume)386 bool PTones::Juxtapose(unsigned frequency1, unsigned frequency2, unsigned milliseconds, unsigned volume)
387 {
388 if (frequency1 < MinFrequency || frequency1 > m_maxFrequency ||
389 frequency2 < MinFrequency || frequency2 > m_maxFrequency)
390 return false;
391
392 // TODO this gived 8000 samples for 100 ms !!!
393 //unsigned samples = CalcSamples(milliseconds, frequency1, frequency2);
394 unsigned samples = milliseconds * m_sampleRate / 1000;
395 while (samples-- > 0) {
396 int a1 = sine(m_angle1, m_sampleRate);
397 int a2 = sine(m_angle2, m_sampleRate);
398
399 AddSample((a1 + a2) / 2, volume);
400
401 m_angle1 += frequency1;
402 if (m_angle1 >= (int)m_sampleRate)
403 m_angle1 -= m_sampleRate;
404
405 m_angle2 += frequency2;
406 if (m_angle2 >= (int)m_sampleRate)
407 m_angle2 -= m_sampleRate;
408 }
409 return true;
410 }
411
412
Modulate(unsigned frequency1,unsigned modulator,unsigned milliseconds,unsigned volume)413 bool PTones::Modulate(unsigned frequency1, unsigned modulator, unsigned milliseconds, unsigned volume)
414 {
415 if (frequency1 > m_maxFrequency || frequency1 > m_maxFrequency || modulator < MinModulation || modulator >= frequency1/2)
416 return false;
417
418 unsigned samples = CalcSamples(milliseconds, frequency1, modulator);
419
420 while (samples-- > 0) {
421 int a1 = sine(m_angle1, m_sampleRate); // -999 to 999
422 int a2 = sine(m_angle2, m_sampleRate); // -999 to 999
423
424 AddSample((a1 * (a2 + SineScale)) / SineScale / 2, volume);
425
426 m_angle1 += frequency1;
427 if (m_angle1 >= (int)m_sampleRate)
428 m_angle1 -= m_sampleRate;
429
430 m_angle2 += modulator;
431 if (m_angle2 >= (int)m_sampleRate)
432 m_angle2 -= m_sampleRate;
433 }
434 return true;
435 }
436
437 static unsigned char tone_2100[320] = {
438 0x00, 0x00, 0xF4, 0x3F, 0xF7, 0xF5, 0xA0, 0xC1, 0xD2, 0x13, 0x44, 0x3B, 0xE1, 0xE2, 0x4E, 0xC9,
439 0xB5, 0x25, 0xC8, 0x30, 0xA3, 0xD2, 0x56, 0xD6, 0xE6, 0x33, 0x84, 0x21, 0xD7, 0xC6, 0x74, 0xE7,
440 0x03, 0x3D, 0xF9, 0x0E, 0xA4, 0xC0, 0xF8, 0xFA, 0x27, 0x40, 0xF7, 0xFA, 0xA4, 0xC0, 0xFA, 0x0E,
441 0x02, 0x3D, 0x74, 0xE7, 0xD7, 0xC6, 0x84, 0x21, 0xE6, 0x33, 0x57, 0xD6, 0xA4, 0xD2, 0xC8, 0x30,
442 0xB4, 0x25, 0x4D, 0xC9, 0xE1, 0xE2, 0x45, 0x3B, 0xD3, 0x13, 0x9F, 0xC1, 0xF7, 0xF5, 0xF4, 0x3F,
443 0x01, 0x00, 0x0D, 0xC0, 0x09, 0x0A, 0x60, 0x3E, 0x2D, 0xEC, 0xBB, 0xC4, 0x20, 0x1D, 0xB3, 0x36,
444 0x4B, 0xDA, 0x38, 0xCF, 0x5C, 0x2D, 0xAA, 0x29, 0x19, 0xCC, 0x7C, 0xDE, 0x28, 0x39, 0x8C, 0x18,
445 0xFE, 0xC2, 0x06, 0xF1, 0x5C, 0x3F, 0x08, 0x05, 0xDA, 0xBF, 0x08, 0x05, 0x5D, 0x3F, 0x07, 0xF1,
446 0xFE, 0xC2, 0x8C, 0x18, 0x29, 0x39, 0x7C, 0xDE, 0x1A, 0xCC, 0xAA, 0x29, 0x5C, 0x2D, 0x38, 0xCF,
447 0x4C, 0xDA, 0xB3, 0x36, 0x20, 0x1D, 0xBC, 0xC4, 0x2D, 0xEC, 0x62, 0x3E, 0x09, 0x0A, 0x0D, 0xC0,
448 0x01, 0x00, 0xF4, 0x3F, 0xF7, 0xF5, 0x9F, 0xC1, 0xD2, 0x13, 0x45, 0x3B, 0xE0, 0xE2, 0x4D, 0xC9,
449 0xB4, 0x25, 0xC7, 0x30, 0xA3, 0xD2, 0x56, 0xD6, 0xE6, 0x33, 0x85, 0x21, 0xD8, 0xC6, 0x74, 0xE7,
450 0x03, 0x3D, 0xFA, 0x0E, 0xA4, 0xC0, 0xF8, 0xFA, 0x26, 0x40, 0xF7, 0xFA, 0xA3, 0xC0, 0xFA, 0x0E,
451 0x03, 0x3D, 0x73, 0xE7, 0xD8, 0xC6, 0x85, 0x21, 0xE6, 0x33, 0x57, 0xD6, 0xA3, 0xD2, 0xC7, 0x30,
452 0xB5, 0x25, 0x4E, 0xC9, 0xE0, 0xE2, 0x44, 0x3B, 0xD3, 0x13, 0x9F, 0xC1, 0xF7, 0xF5, 0xF3, 0x3F,
453 0x00, 0x00, 0x0D, 0xC0, 0x0A, 0x0A, 0x61, 0x3E, 0x2D, 0xEC, 0xBC, 0xC4, 0x1F, 0x1D, 0xB2, 0x36,
454 0x4B, 0xDA, 0x38, 0xCF, 0x5C, 0x2D, 0xA9, 0x29, 0x1A, 0xCC, 0x7B, 0xDE, 0x29, 0x39, 0x8D, 0x18,
455 0xFD, 0xC2, 0x07, 0xF1, 0x5C, 0x3F, 0x08, 0x05, 0xDA, 0xBF, 0x08, 0x05, 0x5B, 0x3F, 0x07, 0xF1,
456 0xFE, 0xC2, 0x8D, 0x18, 0x28, 0x39, 0x7B, 0xDE, 0x19, 0xCC, 0xA9, 0x29, 0x5D, 0x2D, 0x38, 0xCF,
457 0x4B, 0xDA, 0xB2, 0x36, 0x1F, 0x1D, 0xBB, 0xC4, 0x2D, 0xEC, 0x61, 0x3E, 0x09, 0x0A, 0x0C, 0xC0
458 };
459
460
PureTone(unsigned frequency1,unsigned milliseconds,unsigned volume)461 bool PTones::PureTone(unsigned frequency1, unsigned milliseconds, unsigned volume)
462 {
463 if (frequency1 == 2100) {
464 int samples = milliseconds * 8;
465 short * tone = (short *)tone_2100;
466 unsigned int toneLen = sizeof(tone_2100) / 2;
467 PINDEX length;
468 for (length = 0; length < samples; ++length) {
469 PINDEX length = GetSize();
470 SetSize(length + 1);
471 short sample = tone[length % toneLen];
472 //sample *= volume;
473 //sample *= masterVolume;
474 //sample /= SineScale*100*100/SHRT_MAX;
475 SetAt(length, (short)sample);
476 }
477 return true;
478 }
479
480 if (frequency1 < MinFrequency || frequency1 > m_maxFrequency)
481 return false;
482
483 unsigned samples = CalcSamples(milliseconds, frequency1);
484 while (samples-- > 0) {
485 AddSample(sine(m_angle1, m_sampleRate), volume);
486
487 m_angle1 += frequency1;
488 if (m_angle1 >= (int)m_sampleRate)
489 m_angle1 -= m_sampleRate;
490 }
491 return true;
492 }
493
494
Silence(unsigned milliseconds)495 bool PTones::Silence(unsigned milliseconds)
496 {
497 unsigned samples = milliseconds * m_sampleRate/1000;
498 while (samples-- > 0)
499 AddSample(0, 0);
500 return true;
501 }
502
503
CalcSamples(unsigned ms,unsigned f1,unsigned f2)504 unsigned PTones::CalcSamples(unsigned ms, unsigned f1, unsigned f2)
505 {
506 // firstly, find the minimum time to repeat the waveform
507 unsigned v1 = 1;
508 unsigned v2 = 1;
509
510 if (f2 > 0)
511 {
512 while (v1*f2 != v2*f1) {
513 if (v1*f2 < v2*f1)
514 v1++;
515 else
516 v2++;
517 }
518 }
519
520 // v1 repetitions of f1 == v2 repetitions of f2
521 //cout << v1 << " cycles of " << f1 << "hz = " << v2 << " samples of " << f2 << "hz" << endl;
522
523 // now find the number of times we need to repeat this to match the sampling rate
524 unsigned n1 = 1;
525 unsigned n2 = 1;
526 while (n1*m_sampleRate*v1 != n2*f1) {
527 if (n1*m_sampleRate*v1 < n2*f1)
528 n1++;
529 else
530 n2++;
531 }
532
533 // v1 repetitions of t == v2 repetitions sample frequency
534 //cout << n1*v1 << " cycles at " << f1 << "hz = "
535 // << n1*v2 << " cycles at " << f2 << "hz = "
536 // << n2 << " samples at " << m_sampleRate << "hz" << endl;
537
538 // Make sure we round up the number of milliseconds to even multiple of cycles
539 return ms == 0 ? n2 : ((ms * m_sampleRate/1000 + n2 - 1)/n2*n2);
540 }
541
542
AddSample(int sample,unsigned volume)543 void PTones::AddSample(int sample, unsigned volume)
544 {
545 // Sample added is value from -1000 to 1000, rescale to short range -32767 to +32767
546 PINDEX length = GetSize();
547 SetSize(length + 1);
548 sample *= volume;
549 sample *= m_masterVolume;
550 sample /= SineScale*100*100/SHRT_MAX;
551 SetAt(length, (short)sample);
552 }
553
554
555 ////////////////////////////////////////////////////////////////////////
556
PDTMFEncoder(const char * dtmf,unsigned milliseconds)557 PDTMFEncoder::PDTMFEncoder(const char * dtmf, unsigned milliseconds) :
558 PTones()
559 {
560 AddTone(dtmf, milliseconds);
561 }
562
PDTMFEncoder(char digit,unsigned milliseconds)563 PDTMFEncoder::PDTMFEncoder(char digit, unsigned milliseconds) :
564 PTones()
565 {
566 AddTone(digit, milliseconds);
567 }
568
AddTone(const char * str,unsigned milliseconds)569 void PDTMFEncoder::AddTone(const char * str, unsigned milliseconds)
570 {
571 if (str == NULL)
572 return;
573
574 while (*str != '\0')
575 AddTone(*str++, milliseconds);
576 }
577
578
AddTone(char digit,unsigned milliseconds)579 void PDTMFEncoder::AddTone(char digit, unsigned milliseconds)
580 {
581 // DTMF frequencies as per http://www.commlinx.com.au/DTMF_frequencies.htm
582
583 static struct {
584 char code;
585 char operation;
586 unsigned frequency1;
587 unsigned frequency2;
588 } const dtmfData[] = {
589 { '0', '+', 941,1336 },
590 { '1', '+', 697,1209 },
591 { '2', '+', 697,1336 },
592 { '3', '+', 697,1477 },
593 { '4', '+', 770,1209 },
594 { '5', '+', 770,1336 },
595 { '6', '+', 770,1477 },
596 { '7', '+', 852,1209 },
597 { '8', '+', 852,1336 },
598 { '9', '+', 852,1477 },
599 { '*', '+', 941,1209 },
600 { '#', '+', 941,1477 },
601 { 'A', '+', 697,1633 },
602 { 'B', '+', 770,1633 },
603 { 'C', '+', 852,1633 },
604 { 'D', '+', 941,1633 },
605 { 'a', '+', 697,1633 },
606 { 'b', '+', 770,1633 },
607 { 'c', '+', 852,1633 },
608 { 'd', '+', 941,1633 },
609 { 'X', '-', 1100 }, // CNG 1100 hz - sent by originating fax machine after dialing
610 { 'x', '-', 1100 }, // CNG
611 { 'Y', '-', 2100 }, // CED 2100 hz - sent by terminating fax machine after answer to disable echo cancellers
612 { 'y', '-', 2100 } // CED
613 };
614
615 for (PINDEX i = 0; i < PARRAYSIZE(dtmfData); i++) {
616 if (dtmfData[i].code == digit) {
617 Generate(dtmfData[i].operation, dtmfData[i].frequency1, dtmfData[i].frequency2, milliseconds);
618 break;
619 }
620 }
621 }
622
623
AddTone(double f1,double f2,unsigned milliseconds)624 void PDTMFEncoder::AddTone(double f1, double f2, unsigned milliseconds)
625 {
626 if (f1 > 0 && f1 < m_maxFrequency && f2 > 0 && f2 < m_maxFrequency){
627 Generate('+', (unsigned)f1, (unsigned)f2, milliseconds);
628 } else {
629 PAssertAlways(PInvalidParameter);
630 }
631 }
632
633
DtmfChar(PINDEX i)634 char PDTMFEncoder::DtmfChar(PINDEX i)
635 {
636 PAssert(i < 16, "Only 16 dtmf symbols. Index too large");
637
638 static char dtmfSymbols[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','*','#' };
639 return dtmfSymbols[i];
640 }
641
642
643 #endif // P_DTMF
644
645 ////////////////////////////////////////////////////////////////////////////
646