4 Copyright (c) Eicon Networks, 2002.
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
9 Eicon File Revision : 2.1
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
41 #define FILE_ "CAPIDTMF.C"
43 /*---------------------------------------------------------------------------*/
50 /*---------------------------------------------------------------------------*/
52 static short capidtmf_expand_table_alaw[0x0100] =
54 -5504, 5504, -344, 344, -22016, 22016, -1376, 1376,
55 -2752, 2752, -88, 88, -11008, 11008, -688, 688,
56 -7552, 7552, -472, 472, -30208, 30208, -1888, 1888,
57 -3776, 3776, -216, 216, -15104, 15104, -944, 944,
58 -4480, 4480, -280, 280, -17920, 17920, -1120, 1120,
59 -2240, 2240, -24, 24, -8960, 8960, -560, 560,
60 -6528, 6528, -408, 408, -26112, 26112, -1632, 1632,
61 -3264, 3264, -152, 152, -13056, 13056, -816, 816,
62 -6016, 6016, -376, 376, -24064, 24064, -1504, 1504,
63 -3008, 3008, -120, 120, -12032, 12032, -752, 752,
64 -8064, 8064, -504, 504, -32256, 32256, -2016, 2016,
65 -4032, 4032, -248, 248, -16128, 16128, -1008, 1008,
66 -4992, 4992, -312, 312, -19968, 19968, -1248, 1248,
67 -2496, 2496, -56, 56, -9984, 9984, -624, 624,
68 -7040, 7040, -440, 440, -28160, 28160, -1760, 1760,
69 -3520, 3520, -184, 184, -14080, 14080, -880, 880,
70 -5248, 5248, -328, 328, -20992, 20992, -1312, 1312,
71 -2624, 2624, -72, 72, -10496, 10496, -656, 656,
72 -7296, 7296, -456, 456, -29184, 29184, -1824, 1824,
73 -3648, 3648, -200, 200, -14592, 14592, -912, 912,
74 -4224, 4224, -264, 264, -16896, 16896, -1056, 1056,
75 -2112, 2112, -8, 8, -8448, 8448, -528, 528,
76 -6272, 6272, -392, 392, -25088, 25088, -1568, 1568,
77 -3136, 3136, -136, 136, -12544, 12544, -784, 784,
78 -5760, 5760, -360, 360, -23040, 23040, -1440, 1440,
79 -2880, 2880, -104, 104, -11520, 11520, -720, 720,
80 -7808, 7808, -488, 488, -31232, 31232, -1952, 1952,
81 -3904, 3904, -232, 232, -15616, 15616, -976, 976,
82 -4736, 4736, -296, 296, -18944, 18944, -1184, 1184,
83 -2368, 2368, -40, 40, -9472, 9472, -592, 592,
84 -6784, 6784, -424, 424, -27136, 27136, -1696, 1696,
85 -3392, 3392, -168, 168, -13568, 13568, -848, 848
88 static short capidtmf_expand_table_ulaw[0x0100] =
90 -32124, 32124, -1884, 1884, -7932, 7932, -372, 372,
91 -15996, 15996, -876, 876, -3900, 3900, -120, 120,
92 -23932, 23932, -1372, 1372, -5884, 5884, -244, 244,
93 -11900, 11900, -620, 620, -2876, 2876, -56, 56,
94 -28028, 28028, -1628, 1628, -6908, 6908, -308, 308,
95 -13948, 13948, -748, 748, -3388, 3388, -88, 88,
96 -19836, 19836, -1116, 1116, -4860, 4860, -180, 180,
97 -9852, 9852, -492, 492, -2364, 2364, -24, 24,
98 -30076, 30076, -1756, 1756, -7420, 7420, -340, 340,
99 -14972, 14972, -812, 812, -3644, 3644, -104, 104,
100 -21884, 21884, -1244, 1244, -5372, 5372, -212, 212,
101 -10876, 10876, -556, 556, -2620, 2620, -40, 40,
102 -25980, 25980, -1500, 1500, -6396, 6396, -276, 276,
103 -12924, 12924, -684, 684, -3132, 3132, -72, 72,
104 -17788, 17788, -988, 988, -4348, 4348, -148, 148,
105 -8828, 8828, -428, 428, -2108, 2108, -8, 8,
106 -31100, 31100, -1820, 1820, -7676, 7676, -356, 356,
107 -15484, 15484, -844, 844, -3772, 3772, -112, 112,
108 -22908, 22908, -1308, 1308, -5628, 5628, -228, 228,
109 -11388, 11388, -588, 588, -2748, 2748, -48, 48,
110 -27004, 27004, -1564, 1564, -6652, 6652, -292, 292,
111 -13436, 13436, -716, 716, -3260, 3260, -80, 80,
112 -18812, 18812, -1052, 1052, -4604, 4604, -164, 164,
113 -9340, 9340, -460, 460, -2236, 2236, -16, 16,
114 -29052, 29052, -1692, 1692, -7164, 7164, -324, 324,
115 -14460, 14460, -780, 780, -3516, 3516, -96, 96,
116 -20860, 20860, -1180, 1180, -5116, 5116, -196, 196,
117 -10364, 10364, -524, 524, -2492, 2492, -32, 32,
118 -24956, 24956, -1436, 1436, -6140, 6140, -260, 260,
119 -12412, 12412, -652, 652, -3004, 3004, -64, 64,
120 -16764, 16764, -924, 924, -4092, 4092, -132, 132,
121 -8316, 8316, -396, 396, -1980, 1980, 0, 0
125 /*---------------------------------------------------------------------------*/
127 static short capidtmf_recv_window_function[CAPIDTMF_RECV_ACCUMULATE_CYCLES] =
129 -500L, -999L, -1499L, -1998L, -2496L, -2994L, -3491L, -3988L,
130 -4483L, -4978L, -5471L, -5963L, -6454L, -6943L, -7431L, -7917L,
131 -8401L, -8883L, -9363L, -9840L, -10316L, -10789L, -11259L, -11727L,
132 -12193L, -12655L, -13115L, -13571L, -14024L, -14474L, -14921L, -15364L,
133 -15804L, -16240L, -16672L, -17100L, -17524L, -17944L, -18360L, -18772L,
134 -19180L, -19583L, -19981L, -20375L, -20764L, -21148L, -21527L, -21901L,
135 -22270L, -22634L, -22993L, -23346L, -23694L, -24037L, -24374L, -24705L,
136 -25030L, -25350L, -25664L, -25971L, -26273L, -26568L, -26858L, -27141L,
137 -27418L, -27688L, -27952L, -28210L, -28461L, -28705L, -28943L, -29174L,
138 -29398L, -29615L, -29826L, -30029L, -30226L, -30415L, -30598L, -30773L,
139 -30941L, -31102L, -31256L, -31402L, -31541L, -31673L, -31797L, -31914L,
140 -32024L, -32126L, -32221L, -32308L, -32388L, -32460L, -32524L, -32581L,
141 -32631L, -32673L, -32707L, -32734L, -32753L, -32764L, -32768L, -32764L,
142 -32753L, -32734L, -32707L, -32673L, -32631L, -32581L, -32524L, -32460L,
143 -32388L, -32308L, -32221L, -32126L, -32024L, -31914L, -31797L, -31673L,
144 -31541L, -31402L, -31256L, -31102L, -30941L, -30773L, -30598L, -30415L,
145 -30226L, -30029L, -29826L, -29615L, -29398L, -29174L, -28943L, -28705L,
146 -28461L, -28210L, -27952L, -27688L, -27418L, -27141L, -26858L, -26568L,
147 -26273L, -25971L, -25664L, -25350L, -25030L, -24705L, -24374L, -24037L,
148 -23694L, -23346L, -22993L, -22634L, -22270L, -21901L, -21527L, -21148L,
149 -20764L, -20375L, -19981L, -19583L, -19180L, -18772L, -18360L, -17944L,
150 -17524L, -17100L, -16672L, -16240L, -15804L, -15364L, -14921L, -14474L,
151 -14024L, -13571L, -13115L, -12655L, -12193L, -11727L, -11259L, -10789L,
152 -10316L, -9840L, -9363L, -8883L, -8401L, -7917L, -7431L, -6943L,
153 -6454L, -5963L, -5471L, -4978L, -4483L, -3988L, -3491L, -2994L,
154 -2496L, -1998L, -1499L, -999L, -500L,
157 static byte capidtmf_leading_zeroes_table[0x100] =
159 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
160 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
161 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
162 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
163 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
164 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
165 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
166 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
167 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
168 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
169 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
170 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
171 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
172 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
173 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
174 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
177 #define capidtmf_byte_leading_zeroes(b) (capidtmf_leading_zeroes_table[(BYTE)(b)])
178 #define capidtmf_word_leading_zeroes(w) (((w) & 0xff00) ? capidtmf_leading_zeroes_table[(w) >> 8] : 8 + capidtmf_leading_zeroes_table[(w)])
179 #define capidtmf_dword_leading_zeroes(d) (((d) & 0xffff0000L) ? (((d) & 0xff000000L) ? capidtmf_leading_zeroes_table[(d) >> 24] : 8 + capidtmf_leading_zeroes_table[(d) >> 16]) : (((d) & 0xff00) ? 16 + capidtmf_leading_zeroes_table[(d) >> 8] : 24 + capidtmf_leading_zeroes_table[(d)]))
182 /*---------------------------------------------------------------------------*/
185 static void capidtmf_goertzel_loop(long *buffer, long *coeffs, short *sample, long count)
188 long c, d, q0, q1, q2;
190 for (i = 0; i < CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT - 1; i++)
193 q2 = buffer[i + CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT];
198 for (j = 0; j < count; j++)
200 q0 = sample[j] - q2 + (c * (q1 >> 16)) + (((dword)(((dword) d) * ((dword)(q1 & 0xffff)))) >> 15);
209 for (j = 0; j < count; j++)
211 q0 = sample[j] - q2 - ((c * (q1 >> 16)) + (((dword)(((dword) d) * ((dword)(q1 & 0xffff)))) >> 15));
217 buffer[i + CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT] = q2;
220 q2 = buffer[i + CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT];
221 c = (coeffs[i] >> 1) << 1;
224 for (j = 0; j < count; j++)
226 q0 = sample[j] - q2 + (c * (q1 >> 16)) + (((dword)(((dword)(c >> 1)) * ((dword)(q1 & 0xffff)))) >> 15);
229 c -= CAPIDTMF_RECV_FUNDAMENTAL_DECREMENT;
235 for (j = 0; j < count; j++)
237 q0 = sample[j] - q2 - ((c * (q1 >> 16)) + (((dword)(((dword)(c >> 1)) * ((dword)(q1 & 0xffff)))) >> 15));
240 c += CAPIDTMF_RECV_FUNDAMENTAL_DECREMENT;
245 buffer[i + CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT] = q2;
249 static void capidtmf_goertzel_result(long *buffer, long *coeffs)
252 long d, e, q1, q2, lo, mid, hi;
255 for (i = 0; i < CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT; i++)
258 q2 = buffer[i + CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT];
261 d = ((d << 1) * (-q1 >> 16)) + (((dword)(((dword) d) * ((dword)(-q1 & 0xffff)))) >> 15);
263 d = ((-d << 1) * (-q1 >> 16)) + (((dword)(((dword) -d) * ((dword)(-q1 & 0xffff)))) >> 15);
264 e = (q2 >= 0) ? q2 : -q2;
267 k = ((dword)(d & 0xffff)) * ((dword)(e & 0xffff));
270 k = ((dword)(d >> 16)) * ((dword)(e & 0xffff));
273 k = ((dword)(d & 0xffff)) * ((dword)(e >> 16));
276 hi += ((dword)(d >> 16)) * ((dword)(e >> 16));
281 k = ((dword)(d & 0xffff)) * ((dword)(e & 0xffff));
282 lo = -((long)(k & 0xffff));
283 mid = -((long)(k >> 16));
284 k = ((dword)(d >> 16)) * ((dword)(e & 0xffff));
286 hi = -((long)(k >> 16));
287 k = ((dword)(d & 0xffff)) * ((dword)(e >> 16));
290 hi -= ((dword)(d >> 16)) * ((dword)(e >> 16));
298 d = (q1 >= 0) ? q1 : -q1;
299 k = ((dword)(d & 0xffff)) * ((dword)(d & 0xffff));
302 k = ((dword)(d >> 16)) * ((dword)(d & 0xffff));
303 mid += (k & 0xffff) << 1;
304 hi += (k >> 16) << 1;
305 hi += ((dword)(d >> 16)) * ((dword)(d >> 16));
306 d = (q2 >= 0) ? q2 : -q2;
307 k = ((dword)(d & 0xffff)) * ((dword)(d & 0xffff));
310 k = ((dword)(d >> 16)) * ((dword)(d & 0xffff));
311 mid += (k & 0xffff) << 1;
312 hi += (k >> 16) << 1;
313 hi += ((dword)(d >> 16)) * ((dword)(d >> 16));
316 buffer[i] = (lo & 0xffff) | (mid << 16);
317 buffer[i + CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT] = hi;
322 /*---------------------------------------------------------------------------*/
324 #define CAPIDTMF_RECV_GUARD_SNR_INDEX_697 0
325 #define CAPIDTMF_RECV_GUARD_SNR_INDEX_770 1
326 #define CAPIDTMF_RECV_GUARD_SNR_INDEX_852 2
327 #define CAPIDTMF_RECV_GUARD_SNR_INDEX_941 3
328 #define CAPIDTMF_RECV_GUARD_SNR_INDEX_1209 4
329 #define CAPIDTMF_RECV_GUARD_SNR_INDEX_1336 5
330 #define CAPIDTMF_RECV_GUARD_SNR_INDEX_1477 6
331 #define CAPIDTMF_RECV_GUARD_SNR_INDEX_1633 7
332 #define CAPIDTMF_RECV_GUARD_SNR_INDEX_635 8
333 #define CAPIDTMF_RECV_GUARD_SNR_INDEX_1010 9
334 #define CAPIDTMF_RECV_GUARD_SNR_INDEX_1140 10
335 #define CAPIDTMF_RECV_GUARD_SNR_INDEX_1272 11
336 #define CAPIDTMF_RECV_GUARD_SNR_INDEX_1405 12
337 #define CAPIDTMF_RECV_GUARD_SNR_INDEX_1555 13
338 #define CAPIDTMF_RECV_GUARD_SNR_INDEX_1715 14
339 #define CAPIDTMF_RECV_GUARD_SNR_INDEX_1875 15
341 #define CAPIDTMF_RECV_GUARD_SNR_DONTCARE 0xc000
342 #define CAPIDTMF_RECV_NO_DIGIT 0xff
343 #define CAPIDTMF_RECV_TIME_GRANULARITY (CAPIDTMF_RECV_ACCUMULATE_CYCLES + 1)
345 #define CAPIDTMF_RECV_INDICATION_DIGIT 0x0001
347 static long capidtmf_recv_goertzel_coef_table[CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT] =
349 0xda97L * 2, /* 697 Hz (Low group 697 Hz) */
350 0xd299L * 2, /* 770 Hz (Low group 770 Hz) */
351 0xc8cbL * 2, /* 852 Hz (Low group 852 Hz) */
352 0xbd36L * 2, /* 941 Hz (Low group 941 Hz) */
353 0x9501L * 2, /* 1209 Hz (High group 1209 Hz) */
354 0x7f89L * 2, /* 1336 Hz (High group 1336 Hz) */
355 0x6639L * 2, /* 1477 Hz (High group 1477 Hz) */
356 0x48c6L * 2, /* 1633 Hz (High group 1633 Hz) */
357 0xe14cL * 2, /* 630 Hz (Lower guard of low group 631 Hz) */
358 0xb2e0L * 2, /* 1015 Hz (Upper guard of low group 1039 Hz) */
359 0xa1a0L * 2, /* 1130 Hz (Lower guard of high group 1140 Hz) */
360 0x8a87L * 2, /* 1272 Hz (Guard between 1209 Hz and 1336 Hz: 1271 Hz) */
361 0x7353L * 2, /* 1405 Hz (2nd harmonics of 697 Hz and guard between 1336 Hz and 1477 Hz: 1405 Hz) */
362 0x583bL * 2, /* 1552 Hz (2nd harmonics of 770 Hz and guard between 1477 Hz and 1633 Hz: 1553 Hz) */
363 0x37d8L * 2, /* 1720 Hz (2nd harmonics of 852 Hz and upper guard of high group: 1715 Hz) */
364 0x0000L * 2 /* 100-630 Hz (fundamentals) */
368 static word capidtmf_recv_guard_snr_low_table[CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT] =
370 14, /* Low group peak versus 697 Hz */
371 14, /* Low group peak versus 770 Hz */
372 16, /* Low group peak versus 852 Hz */
373 16, /* Low group peak versus 941 Hz */
374 CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* Low group peak versus 1209 Hz */
375 CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* Low group peak versus 1336 Hz */
376 CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* Low group peak versus 1477 Hz */
377 CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* Low group peak versus 1633 Hz */
378 14, /* Low group peak versus 635 Hz */
379 16, /* Low group peak versus 1010 Hz */
380 CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* Low group peak versus 1140 Hz */
381 CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* Low group peak versus 1272 Hz */
382 DSPDTMF_RX_HARMONICS_SEL_DEFAULT - 8, /* Low group peak versus 1405 Hz */
383 DSPDTMF_RX_HARMONICS_SEL_DEFAULT - 4, /* Low group peak versus 1555 Hz */
384 DSPDTMF_RX_HARMONICS_SEL_DEFAULT - 4, /* Low group peak versus 1715 Hz */
385 12 /* Low group peak versus 100-630 Hz */
389 static word capidtmf_recv_guard_snr_high_table[CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT] =
391 CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* High group peak versus 697 Hz */
392 CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* High group peak versus 770 Hz */
393 CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* High group peak versus 852 Hz */
394 CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* High group peak versus 941 Hz */
395 20, /* High group peak versus 1209 Hz */
396 20, /* High group peak versus 1336 Hz */
397 20, /* High group peak versus 1477 Hz */
398 20, /* High group peak versus 1633 Hz */
399 CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* High group peak versus 635 Hz */
400 CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* High group peak versus 1010 Hz */
401 16, /* High group peak versus 1140 Hz */
402 4, /* High group peak versus 1272 Hz */
403 6, /* High group peak versus 1405 Hz */
404 8, /* High group peak versus 1555 Hz */
405 16, /* High group peak versus 1715 Hz */
406 12 /* High group peak versus 100-630 Hz */
410 /*---------------------------------------------------------------------------*/
412 static void capidtmf_recv_init(t_capidtmf_state *p_state)
414 p_state->recv.min_gap_duration = 1;
415 p_state->recv.min_digit_duration = 1;
417 p_state->recv.cycle_counter = 0;
418 p_state->recv.current_digit_on_time = 0;
419 p_state->recv.current_digit_off_time = 0;
420 p_state->recv.current_digit_value = CAPIDTMF_RECV_NO_DIGIT;
422 p_state->recv.digit_write_pos = 0;
423 p_state->recv.digit_read_pos = 0;
424 p_state->recv.indication_state = 0;
425 p_state->recv.indication_state_ack = 0;
426 p_state->recv.state = CAPIDTMF_RECV_STATE_IDLE;
430 void capidtmf_recv_enable(t_capidtmf_state *p_state, word min_digit_duration, word min_gap_duration)
432 p_state->recv.indication_state_ack &= CAPIDTMF_RECV_INDICATION_DIGIT;
433 p_state->recv.min_digit_duration = (word)(((((dword) min_digit_duration) * 8) +
434 ((dword)(CAPIDTMF_RECV_TIME_GRANULARITY / 2))) / ((dword) CAPIDTMF_RECV_TIME_GRANULARITY));
435 if (p_state->recv.min_digit_duration <= 1)
436 p_state->recv.min_digit_duration = 1;
438 (p_state->recv.min_digit_duration)--;
439 p_state->recv.min_gap_duration =
440 (word)((((dword) min_gap_duration) * 8) / ((dword) CAPIDTMF_RECV_TIME_GRANULARITY));
441 if (p_state->recv.min_gap_duration <= 1)
442 p_state->recv.min_gap_duration = 1;
444 (p_state->recv.min_gap_duration)--;
445 p_state->recv.state |= CAPIDTMF_RECV_STATE_DTMF_ACTIVE;
449 void capidtmf_recv_disable(t_capidtmf_state *p_state)
451 p_state->recv.state &= ~CAPIDTMF_RECV_STATE_DTMF_ACTIVE;
452 if (p_state->recv.state == CAPIDTMF_RECV_STATE_IDLE)
453 capidtmf_recv_init(p_state);
456 p_state->recv.cycle_counter = 0;
457 p_state->recv.current_digit_on_time = 0;
458 p_state->recv.current_digit_off_time = 0;
459 p_state->recv.current_digit_value = CAPIDTMF_RECV_NO_DIGIT;
464 word capidtmf_recv_indication(t_capidtmf_state *p_state, byte *buffer)
468 flags = p_state->recv.indication_state ^ p_state->recv.indication_state_ack;
469 p_state->recv.indication_state_ack ^= flags & CAPIDTMF_RECV_INDICATION_DIGIT;
470 if (p_state->recv.digit_write_pos != p_state->recv.digit_read_pos)
473 k = p_state->recv.digit_write_pos;
474 j = p_state->recv.digit_read_pos;
477 buffer[i++] = p_state->recv.digit_buffer[j];
478 j = (j == CAPIDTMF_RECV_DIGIT_BUFFER_SIZE - 1) ? 0 : j + 1;
480 p_state->recv.digit_read_pos = k;
483 p_state->recv.indication_state_ack ^= flags;
488 #define CAPIDTMF_RECV_WINDOWED_SAMPLES 32
490 void capidtmf_recv_block(t_capidtmf_state *p_state, byte *buffer, word length)
493 word sample_number, cycle_counter, n, i;
494 word low_peak, high_peak;
498 byte goertzel_result_buffer[CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT];
499 short windowed_sample_buffer[CAPIDTMF_RECV_WINDOWED_SAMPLES];
502 if (p_state->recv.state & CAPIDTMF_RECV_STATE_DTMF_ACTIVE)
504 cycle_counter = p_state->recv.cycle_counter;
506 while (sample_number < length)
508 if (cycle_counter < CAPIDTMF_RECV_ACCUMULATE_CYCLES)
510 if (cycle_counter == 0)
512 for (i = 0; i < CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT; i++)
514 p_state->recv.goertzel_buffer[0][i] = 0;
515 p_state->recv.goertzel_buffer[1][i] = 0;
518 n = CAPIDTMF_RECV_ACCUMULATE_CYCLES - cycle_counter;
519 if (n > length - sample_number)
520 n = length - sample_number;
521 if (n > CAPIDTMF_RECV_WINDOWED_SAMPLES)
522 n = CAPIDTMF_RECV_WINDOWED_SAMPLES;
523 p = buffer + sample_number;
524 q = capidtmf_recv_window_function + cycle_counter;
527 for (i = 0; i < n; i++)
529 windowed_sample_buffer[i] =
530 (short)((capidtmf_expand_table_ulaw[p[i]] * ((long)(q[i]))) >> 15);
535 for (i = 0; i < n; i++)
537 windowed_sample_buffer[i] =
538 (short)((capidtmf_expand_table_alaw[p[i]] * ((long)(q[i]))) >> 15);
541 capidtmf_recv_goertzel_coef_table[CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT - 1] = CAPIDTMF_RECV_FUNDAMENTAL_OFFSET;
542 capidtmf_goertzel_loop(p_state->recv.goertzel_buffer[0],
543 capidtmf_recv_goertzel_coef_table, windowed_sample_buffer, n);
549 capidtmf_goertzel_result(p_state->recv.goertzel_buffer[0],
550 capidtmf_recv_goertzel_coef_table);
551 for (i = 0; i < CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT; i++)
553 lo = (dword)(p_state->recv.goertzel_buffer[0][i]);
554 hi = (dword)(p_state->recv.goertzel_buffer[1][i]);
557 n = capidtmf_dword_leading_zeroes(hi);
558 hi = (hi << n) | (lo >> (32 - n));
562 n = capidtmf_dword_leading_zeroes(lo);
567 if (hi >= 0xcb300000L)
569 else if (hi >= 0xa1450000L)
571 goertzel_result_buffer[i] = (byte) n;
573 low_peak = DSPDTMF_RX_SENSITIVITY_LOW_DEFAULT;
574 result_digit = CAPIDTMF_RECV_NO_DIGIT;
575 for (i = 0; i < CAPIDTMF_LOW_GROUP_FREQUENCIES; i++)
577 if (goertzel_result_buffer[i] > low_peak)
579 low_peak = goertzel_result_buffer[i];
580 result_digit = (byte) i;
583 high_peak = DSPDTMF_RX_SENSITIVITY_HIGH_DEFAULT;
584 n = CAPIDTMF_RECV_NO_DIGIT;
585 for (i = CAPIDTMF_LOW_GROUP_FREQUENCIES; i < CAPIDTMF_RECV_BASE_FREQUENCY_COUNT; i++)
587 if (goertzel_result_buffer[i] > high_peak)
589 high_peak = goertzel_result_buffer[i];
590 n = (i - CAPIDTMF_LOW_GROUP_FREQUENCIES) << 2;
593 result_digit |= (byte) n;
594 if (low_peak + DSPDTMF_RX_HIGH_EXCEEDING_LOW_DEFAULT < high_peak)
595 result_digit = CAPIDTMF_RECV_NO_DIGIT;
596 if (high_peak + DSPDTMF_RX_LOW_EXCEEDING_HIGH_DEFAULT < low_peak)
597 result_digit = CAPIDTMF_RECV_NO_DIGIT;
599 for (i = 0; i < CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT; i++)
601 if ((((short)(low_peak - goertzel_result_buffer[i] - capidtmf_recv_guard_snr_low_table[i])) < 0)
602 || (((short)(high_peak - goertzel_result_buffer[i] - capidtmf_recv_guard_snr_high_table[i])) < 0))
608 result_digit = CAPIDTMF_RECV_NO_DIGIT;
610 if (result_digit == CAPIDTMF_RECV_NO_DIGIT)
612 if (p_state->recv.current_digit_on_time != 0)
614 if (++(p_state->recv.current_digit_off_time) >= p_state->recv.min_gap_duration)
616 p_state->recv.current_digit_on_time = 0;
617 p_state->recv.current_digit_off_time = 0;
622 if (p_state->recv.current_digit_off_time != 0)
623 (p_state->recv.current_digit_off_time)--;
628 if ((p_state->recv.current_digit_on_time == 0)
629 && (p_state->recv.current_digit_off_time != 0))
631 (p_state->recv.current_digit_off_time)--;
635 n = p_state->recv.current_digit_off_time;
636 if ((p_state->recv.current_digit_on_time != 0)
637 && (result_digit != p_state->recv.current_digit_value))
639 p_state->recv.current_digit_on_time = 0;
642 p_state->recv.current_digit_value = result_digit;
643 p_state->recv.current_digit_off_time = 0;
644 if (p_state->recv.current_digit_on_time != 0xffff)
646 p_state->recv.current_digit_on_time += n + 1;
647 if (p_state->recv.current_digit_on_time >= p_state->recv.min_digit_duration)
649 p_state->recv.current_digit_on_time = 0xffff;
650 i = (p_state->recv.digit_write_pos == CAPIDTMF_RECV_DIGIT_BUFFER_SIZE - 1) ?
651 0 : p_state->recv.digit_write_pos + 1;
652 if (i == p_state->recv.digit_read_pos)
654 trace(dprintf("%s,%d: Receive digit overrun",
655 (char *)(FILE_), __LINE__));
659 p_state->recv.digit_buffer[p_state->recv.digit_write_pos] = result_digit;
660 p_state->recv.digit_write_pos = i;
661 p_state->recv.indication_state =
662 (p_state->recv.indication_state & ~CAPIDTMF_RECV_INDICATION_DIGIT) |
663 (~p_state->recv.indication_state_ack & CAPIDTMF_RECV_INDICATION_DIGIT);
673 p_state->recv.cycle_counter = cycle_counter;
678 void capidtmf_init(t_capidtmf_state *p_state, byte ulaw)
680 p_state->ulaw = ulaw;
681 capidtmf_recv_init(p_state);
685 /*---------------------------------------------------------------------------*/