capidtmf.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686
  1. /*
  2. *
  3. Copyright (c) Eicon Networks, 2002.
  4. *
  5. This source file is supplied for the use with
  6. Eicon Networks range of DIVA Server Adapters.
  7. *
  8. Eicon File Revision : 2.1
  9. *
  10. This program is free software; you can redistribute it and/or modify
  11. it under the terms of the GNU General Public License as published by
  12. the Free Software Foundation; either version 2, or (at your option)
  13. any later version.
  14. *
  15. This program is distributed in the hope that it will be useful,
  16. but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
  17. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  18. See the GNU General Public License for more details.
  19. *
  20. You should have received a copy of the GNU General Public License
  21. along with this program; if not, write to the Free Software
  22. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  23. *
  24. */
  25. #include "platform.h"
  26. #include "capidtmf.h"
  27. /* #define TRACE_ */
  28. #define FILE_ "CAPIDTMF.C"
  29. /*---------------------------------------------------------------------------*/
  30. #define trace(a)
  31. /*---------------------------------------------------------------------------*/
  32. static short capidtmf_expand_table_alaw[0x0100] =
  33. {
  34. -5504, 5504, -344, 344, -22016, 22016, -1376, 1376,
  35. -2752, 2752, -88, 88, -11008, 11008, -688, 688,
  36. -7552, 7552, -472, 472, -30208, 30208, -1888, 1888,
  37. -3776, 3776, -216, 216, -15104, 15104, -944, 944,
  38. -4480, 4480, -280, 280, -17920, 17920, -1120, 1120,
  39. -2240, 2240, -24, 24, -8960, 8960, -560, 560,
  40. -6528, 6528, -408, 408, -26112, 26112, -1632, 1632,
  41. -3264, 3264, -152, 152, -13056, 13056, -816, 816,
  42. -6016, 6016, -376, 376, -24064, 24064, -1504, 1504,
  43. -3008, 3008, -120, 120, -12032, 12032, -752, 752,
  44. -8064, 8064, -504, 504, -32256, 32256, -2016, 2016,
  45. -4032, 4032, -248, 248, -16128, 16128, -1008, 1008,
  46. -4992, 4992, -312, 312, -19968, 19968, -1248, 1248,
  47. -2496, 2496, -56, 56, -9984, 9984, -624, 624,
  48. -7040, 7040, -440, 440, -28160, 28160, -1760, 1760,
  49. -3520, 3520, -184, 184, -14080, 14080, -880, 880,
  50. -5248, 5248, -328, 328, -20992, 20992, -1312, 1312,
  51. -2624, 2624, -72, 72, -10496, 10496, -656, 656,
  52. -7296, 7296, -456, 456, -29184, 29184, -1824, 1824,
  53. -3648, 3648, -200, 200, -14592, 14592, -912, 912,
  54. -4224, 4224, -264, 264, -16896, 16896, -1056, 1056,
  55. -2112, 2112, -8, 8, -8448, 8448, -528, 528,
  56. -6272, 6272, -392, 392, -25088, 25088, -1568, 1568,
  57. -3136, 3136, -136, 136, -12544, 12544, -784, 784,
  58. -5760, 5760, -360, 360, -23040, 23040, -1440, 1440,
  59. -2880, 2880, -104, 104, -11520, 11520, -720, 720,
  60. -7808, 7808, -488, 488, -31232, 31232, -1952, 1952,
  61. -3904, 3904, -232, 232, -15616, 15616, -976, 976,
  62. -4736, 4736, -296, 296, -18944, 18944, -1184, 1184,
  63. -2368, 2368, -40, 40, -9472, 9472, -592, 592,
  64. -6784, 6784, -424, 424, -27136, 27136, -1696, 1696,
  65. -3392, 3392, -168, 168, -13568, 13568, -848, 848
  66. };
  67. static short capidtmf_expand_table_ulaw[0x0100] =
  68. {
  69. -32124, 32124, -1884, 1884, -7932, 7932, -372, 372,
  70. -15996, 15996, -876, 876, -3900, 3900, -120, 120,
  71. -23932, 23932, -1372, 1372, -5884, 5884, -244, 244,
  72. -11900, 11900, -620, 620, -2876, 2876, -56, 56,
  73. -28028, 28028, -1628, 1628, -6908, 6908, -308, 308,
  74. -13948, 13948, -748, 748, -3388, 3388, -88, 88,
  75. -19836, 19836, -1116, 1116, -4860, 4860, -180, 180,
  76. -9852, 9852, -492, 492, -2364, 2364, -24, 24,
  77. -30076, 30076, -1756, 1756, -7420, 7420, -340, 340,
  78. -14972, 14972, -812, 812, -3644, 3644, -104, 104,
  79. -21884, 21884, -1244, 1244, -5372, 5372, -212, 212,
  80. -10876, 10876, -556, 556, -2620, 2620, -40, 40,
  81. -25980, 25980, -1500, 1500, -6396, 6396, -276, 276,
  82. -12924, 12924, -684, 684, -3132, 3132, -72, 72,
  83. -17788, 17788, -988, 988, -4348, 4348, -148, 148,
  84. -8828, 8828, -428, 428, -2108, 2108, -8, 8,
  85. -31100, 31100, -1820, 1820, -7676, 7676, -356, 356,
  86. -15484, 15484, -844, 844, -3772, 3772, -112, 112,
  87. -22908, 22908, -1308, 1308, -5628, 5628, -228, 228,
  88. -11388, 11388, -588, 588, -2748, 2748, -48, 48,
  89. -27004, 27004, -1564, 1564, -6652, 6652, -292, 292,
  90. -13436, 13436, -716, 716, -3260, 3260, -80, 80,
  91. -18812, 18812, -1052, 1052, -4604, 4604, -164, 164,
  92. -9340, 9340, -460, 460, -2236, 2236, -16, 16,
  93. -29052, 29052, -1692, 1692, -7164, 7164, -324, 324,
  94. -14460, 14460, -780, 780, -3516, 3516, -96, 96,
  95. -20860, 20860, -1180, 1180, -5116, 5116, -196, 196,
  96. -10364, 10364, -524, 524, -2492, 2492, -32, 32,
  97. -24956, 24956, -1436, 1436, -6140, 6140, -260, 260,
  98. -12412, 12412, -652, 652, -3004, 3004, -64, 64,
  99. -16764, 16764, -924, 924, -4092, 4092, -132, 132,
  100. -8316, 8316, -396, 396, -1980, 1980, 0, 0
  101. };
  102. /*---------------------------------------------------------------------------*/
  103. static short capidtmf_recv_window_function[CAPIDTMF_RECV_ACCUMULATE_CYCLES] =
  104. {
  105. -500L, -999L, -1499L, -1998L, -2496L, -2994L, -3491L, -3988L,
  106. -4483L, -4978L, -5471L, -5963L, -6454L, -6943L, -7431L, -7917L,
  107. -8401L, -8883L, -9363L, -9840L, -10316L, -10789L, -11259L, -11727L,
  108. -12193L, -12655L, -13115L, -13571L, -14024L, -14474L, -14921L, -15364L,
  109. -15804L, -16240L, -16672L, -17100L, -17524L, -17944L, -18360L, -18772L,
  110. -19180L, -19583L, -19981L, -20375L, -20764L, -21148L, -21527L, -21901L,
  111. -22270L, -22634L, -22993L, -23346L, -23694L, -24037L, -24374L, -24705L,
  112. -25030L, -25350L, -25664L, -25971L, -26273L, -26568L, -26858L, -27141L,
  113. -27418L, -27688L, -27952L, -28210L, -28461L, -28705L, -28943L, -29174L,
  114. -29398L, -29615L, -29826L, -30029L, -30226L, -30415L, -30598L, -30773L,
  115. -30941L, -31102L, -31256L, -31402L, -31541L, -31673L, -31797L, -31914L,
  116. -32024L, -32126L, -32221L, -32308L, -32388L, -32460L, -32524L, -32581L,
  117. -32631L, -32673L, -32707L, -32734L, -32753L, -32764L, -32768L, -32764L,
  118. -32753L, -32734L, -32707L, -32673L, -32631L, -32581L, -32524L, -32460L,
  119. -32388L, -32308L, -32221L, -32126L, -32024L, -31914L, -31797L, -31673L,
  120. -31541L, -31402L, -31256L, -31102L, -30941L, -30773L, -30598L, -30415L,
  121. -30226L, -30029L, -29826L, -29615L, -29398L, -29174L, -28943L, -28705L,
  122. -28461L, -28210L, -27952L, -27688L, -27418L, -27141L, -26858L, -26568L,
  123. -26273L, -25971L, -25664L, -25350L, -25030L, -24705L, -24374L, -24037L,
  124. -23694L, -23346L, -22993L, -22634L, -22270L, -21901L, -21527L, -21148L,
  125. -20764L, -20375L, -19981L, -19583L, -19180L, -18772L, -18360L, -17944L,
  126. -17524L, -17100L, -16672L, -16240L, -15804L, -15364L, -14921L, -14474L,
  127. -14024L, -13571L, -13115L, -12655L, -12193L, -11727L, -11259L, -10789L,
  128. -10316L, -9840L, -9363L, -8883L, -8401L, -7917L, -7431L, -6943L,
  129. -6454L, -5963L, -5471L, -4978L, -4483L, -3988L, -3491L, -2994L,
  130. -2496L, -1998L, -1499L, -999L, -500L,
  131. };
  132. static byte capidtmf_leading_zeroes_table[0x100] =
  133. {
  134. 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
  135. 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  136. 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  137. 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  138. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  139. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  140. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  141. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  142. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  143. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  144. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  145. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  146. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  147. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  148. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  149. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  150. };
  151. #define capidtmf_byte_leading_zeroes(b) (capidtmf_leading_zeroes_table[(BYTE)(b)])
  152. #define capidtmf_word_leading_zeroes(w) (((w) & 0xff00) ? capidtmf_leading_zeroes_table[(w) >> 8] : 8 + capidtmf_leading_zeroes_table[(w)])
  153. #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)]))
  154. /*---------------------------------------------------------------------------*/
  155. static void capidtmf_goertzel_loop(long *buffer, long *coeffs, short *sample, long count)
  156. {
  157. int i, j;
  158. long c, d, q0, q1, q2;
  159. for (i = 0; i < CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT - 1; i++)
  160. {
  161. q1 = buffer[i];
  162. q2 = buffer[i + CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT];
  163. d = coeffs[i] >> 1;
  164. c = d << 1;
  165. if (c >= 0)
  166. {
  167. for (j = 0; j < count; j++)
  168. {
  169. q0 = sample[j] - q2 + (c * (q1 >> 16)) + (((dword)(((dword) d) * ((dword)(q1 & 0xffff)))) >> 15);
  170. q2 = q1;
  171. q1 = q0;
  172. }
  173. }
  174. else
  175. {
  176. c = -c;
  177. d = -d;
  178. for (j = 0; j < count; j++)
  179. {
  180. q0 = sample[j] - q2 - ((c * (q1 >> 16)) + (((dword)(((dword) d) * ((dword)(q1 & 0xffff)))) >> 15));
  181. q2 = q1;
  182. q1 = q0;
  183. }
  184. }
  185. buffer[i] = q1;
  186. buffer[i + CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT] = q2;
  187. }
  188. q1 = buffer[i];
  189. q2 = buffer[i + CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT];
  190. c = (coeffs[i] >> 1) << 1;
  191. if (c >= 0)
  192. {
  193. for (j = 0; j < count; j++)
  194. {
  195. q0 = sample[j] - q2 + (c * (q1 >> 16)) + (((dword)(((dword)(c >> 1)) * ((dword)(q1 & 0xffff)))) >> 15);
  196. q2 = q1;
  197. q1 = q0;
  198. c -= CAPIDTMF_RECV_FUNDAMENTAL_DECREMENT;
  199. }
  200. }
  201. else
  202. {
  203. c = -c;
  204. for (j = 0; j < count; j++)
  205. {
  206. q0 = sample[j] - q2 - ((c * (q1 >> 16)) + (((dword)(((dword)(c >> 1)) * ((dword)(q1 & 0xffff)))) >> 15));
  207. q2 = q1;
  208. q1 = q0;
  209. c += CAPIDTMF_RECV_FUNDAMENTAL_DECREMENT;
  210. }
  211. }
  212. coeffs[i] = c;
  213. buffer[i] = q1;
  214. buffer[i + CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT] = q2;
  215. }
  216. static void capidtmf_goertzel_result(long *buffer, long *coeffs)
  217. {
  218. int i;
  219. long d, e, q1, q2, lo, mid, hi;
  220. dword k;
  221. for (i = 0; i < CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT; i++)
  222. {
  223. q1 = buffer[i];
  224. q2 = buffer[i + CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT];
  225. d = coeffs[i] >> 1;
  226. if (d >= 0)
  227. d = ((d << 1) * (-q1 >> 16)) + (((dword)(((dword) d) * ((dword)(-q1 & 0xffff)))) >> 15);
  228. else
  229. d = ((-d << 1) * (-q1 >> 16)) + (((dword)(((dword) -d) * ((dword)(-q1 & 0xffff)))) >> 15);
  230. e = (q2 >= 0) ? q2 : -q2;
  231. if (d >= 0)
  232. {
  233. k = ((dword)(d & 0xffff)) * ((dword)(e & 0xffff));
  234. lo = k & 0xffff;
  235. mid = k >> 16;
  236. k = ((dword)(d >> 16)) * ((dword)(e & 0xffff));
  237. mid += k & 0xffff;
  238. hi = k >> 16;
  239. k = ((dword)(d & 0xffff)) * ((dword)(e >> 16));
  240. mid += k & 0xffff;
  241. hi += k >> 16;
  242. hi += ((dword)(d >> 16)) * ((dword)(e >> 16));
  243. }
  244. else
  245. {
  246. d = -d;
  247. k = ((dword)(d & 0xffff)) * ((dword)(e & 0xffff));
  248. lo = -((long)(k & 0xffff));
  249. mid = -((long)(k >> 16));
  250. k = ((dword)(d >> 16)) * ((dword)(e & 0xffff));
  251. mid -= k & 0xffff;
  252. hi = -((long)(k >> 16));
  253. k = ((dword)(d & 0xffff)) * ((dword)(e >> 16));
  254. mid -= k & 0xffff;
  255. hi -= k >> 16;
  256. hi -= ((dword)(d >> 16)) * ((dword)(e >> 16));
  257. }
  258. if (q2 < 0)
  259. {
  260. lo = -lo;
  261. mid = -mid;
  262. hi = -hi;
  263. }
  264. d = (q1 >= 0) ? q1 : -q1;
  265. k = ((dword)(d & 0xffff)) * ((dword)(d & 0xffff));
  266. lo += k & 0xffff;
  267. mid += k >> 16;
  268. k = ((dword)(d >> 16)) * ((dword)(d & 0xffff));
  269. mid += (k & 0xffff) << 1;
  270. hi += (k >> 16) << 1;
  271. hi += ((dword)(d >> 16)) * ((dword)(d >> 16));
  272. d = (q2 >= 0) ? q2 : -q2;
  273. k = ((dword)(d & 0xffff)) * ((dword)(d & 0xffff));
  274. lo += k & 0xffff;
  275. mid += k >> 16;
  276. k = ((dword)(d >> 16)) * ((dword)(d & 0xffff));
  277. mid += (k & 0xffff) << 1;
  278. hi += (k >> 16) << 1;
  279. hi += ((dword)(d >> 16)) * ((dword)(d >> 16));
  280. mid += lo >> 16;
  281. hi += mid >> 16;
  282. buffer[i] = (lo & 0xffff) | (mid << 16);
  283. buffer[i + CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT] = hi;
  284. }
  285. }
  286. /*---------------------------------------------------------------------------*/
  287. #define CAPIDTMF_RECV_GUARD_SNR_INDEX_697 0
  288. #define CAPIDTMF_RECV_GUARD_SNR_INDEX_770 1
  289. #define CAPIDTMF_RECV_GUARD_SNR_INDEX_852 2
  290. #define CAPIDTMF_RECV_GUARD_SNR_INDEX_941 3
  291. #define CAPIDTMF_RECV_GUARD_SNR_INDEX_1209 4
  292. #define CAPIDTMF_RECV_GUARD_SNR_INDEX_1336 5
  293. #define CAPIDTMF_RECV_GUARD_SNR_INDEX_1477 6
  294. #define CAPIDTMF_RECV_GUARD_SNR_INDEX_1633 7
  295. #define CAPIDTMF_RECV_GUARD_SNR_INDEX_635 8
  296. #define CAPIDTMF_RECV_GUARD_SNR_INDEX_1010 9
  297. #define CAPIDTMF_RECV_GUARD_SNR_INDEX_1140 10
  298. #define CAPIDTMF_RECV_GUARD_SNR_INDEX_1272 11
  299. #define CAPIDTMF_RECV_GUARD_SNR_INDEX_1405 12
  300. #define CAPIDTMF_RECV_GUARD_SNR_INDEX_1555 13
  301. #define CAPIDTMF_RECV_GUARD_SNR_INDEX_1715 14
  302. #define CAPIDTMF_RECV_GUARD_SNR_INDEX_1875 15
  303. #define CAPIDTMF_RECV_GUARD_SNR_DONTCARE 0xc000
  304. #define CAPIDTMF_RECV_NO_DIGIT 0xff
  305. #define CAPIDTMF_RECV_TIME_GRANULARITY (CAPIDTMF_RECV_ACCUMULATE_CYCLES + 1)
  306. #define CAPIDTMF_RECV_INDICATION_DIGIT 0x0001
  307. static long capidtmf_recv_goertzel_coef_table[CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT] =
  308. {
  309. 0xda97L * 2, /* 697 Hz (Low group 697 Hz) */
  310. 0xd299L * 2, /* 770 Hz (Low group 770 Hz) */
  311. 0xc8cbL * 2, /* 852 Hz (Low group 852 Hz) */
  312. 0xbd36L * 2, /* 941 Hz (Low group 941 Hz) */
  313. 0x9501L * 2, /* 1209 Hz (High group 1209 Hz) */
  314. 0x7f89L * 2, /* 1336 Hz (High group 1336 Hz) */
  315. 0x6639L * 2, /* 1477 Hz (High group 1477 Hz) */
  316. 0x48c6L * 2, /* 1633 Hz (High group 1633 Hz) */
  317. 0xe14cL * 2, /* 630 Hz (Lower guard of low group 631 Hz) */
  318. 0xb2e0L * 2, /* 1015 Hz (Upper guard of low group 1039 Hz) */
  319. 0xa1a0L * 2, /* 1130 Hz (Lower guard of high group 1140 Hz) */
  320. 0x8a87L * 2, /* 1272 Hz (Guard between 1209 Hz and 1336 Hz: 1271 Hz) */
  321. 0x7353L * 2, /* 1405 Hz (2nd harmonics of 697 Hz and guard between 1336 Hz and 1477 Hz: 1405 Hz) */
  322. 0x583bL * 2, /* 1552 Hz (2nd harmonics of 770 Hz and guard between 1477 Hz and 1633 Hz: 1553 Hz) */
  323. 0x37d8L * 2, /* 1720 Hz (2nd harmonics of 852 Hz and upper guard of high group: 1715 Hz) */
  324. 0x0000L * 2 /* 100-630 Hz (fundamentals) */
  325. };
  326. static word capidtmf_recv_guard_snr_low_table[CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT] =
  327. {
  328. 14, /* Low group peak versus 697 Hz */
  329. 14, /* Low group peak versus 770 Hz */
  330. 16, /* Low group peak versus 852 Hz */
  331. 16, /* Low group peak versus 941 Hz */
  332. CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* Low group peak versus 1209 Hz */
  333. CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* Low group peak versus 1336 Hz */
  334. CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* Low group peak versus 1477 Hz */
  335. CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* Low group peak versus 1633 Hz */
  336. 14, /* Low group peak versus 635 Hz */
  337. 16, /* Low group peak versus 1010 Hz */
  338. CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* Low group peak versus 1140 Hz */
  339. CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* Low group peak versus 1272 Hz */
  340. DSPDTMF_RX_HARMONICS_SEL_DEFAULT - 8, /* Low group peak versus 1405 Hz */
  341. DSPDTMF_RX_HARMONICS_SEL_DEFAULT - 4, /* Low group peak versus 1555 Hz */
  342. DSPDTMF_RX_HARMONICS_SEL_DEFAULT - 4, /* Low group peak versus 1715 Hz */
  343. 12 /* Low group peak versus 100-630 Hz */
  344. };
  345. static word capidtmf_recv_guard_snr_high_table[CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT] =
  346. {
  347. CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* High group peak versus 697 Hz */
  348. CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* High group peak versus 770 Hz */
  349. CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* High group peak versus 852 Hz */
  350. CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* High group peak versus 941 Hz */
  351. 20, /* High group peak versus 1209 Hz */
  352. 20, /* High group peak versus 1336 Hz */
  353. 20, /* High group peak versus 1477 Hz */
  354. 20, /* High group peak versus 1633 Hz */
  355. CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* High group peak versus 635 Hz */
  356. CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* High group peak versus 1010 Hz */
  357. 16, /* High group peak versus 1140 Hz */
  358. 4, /* High group peak versus 1272 Hz */
  359. 6, /* High group peak versus 1405 Hz */
  360. 8, /* High group peak versus 1555 Hz */
  361. 16, /* High group peak versus 1715 Hz */
  362. 12 /* High group peak versus 100-630 Hz */
  363. };
  364. /*---------------------------------------------------------------------------*/
  365. static void capidtmf_recv_init(t_capidtmf_state *p_state)
  366. {
  367. p_state->recv.min_gap_duration = 1;
  368. p_state->recv.min_digit_duration = 1;
  369. p_state->recv.cycle_counter = 0;
  370. p_state->recv.current_digit_on_time = 0;
  371. p_state->recv.current_digit_off_time = 0;
  372. p_state->recv.current_digit_value = CAPIDTMF_RECV_NO_DIGIT;
  373. p_state->recv.digit_write_pos = 0;
  374. p_state->recv.digit_read_pos = 0;
  375. p_state->recv.indication_state = 0;
  376. p_state->recv.indication_state_ack = 0;
  377. p_state->recv.state = CAPIDTMF_RECV_STATE_IDLE;
  378. }
  379. void capidtmf_recv_enable(t_capidtmf_state *p_state, word min_digit_duration, word min_gap_duration)
  380. {
  381. p_state->recv.indication_state_ack &= CAPIDTMF_RECV_INDICATION_DIGIT;
  382. p_state->recv.min_digit_duration = (word)(((((dword) min_digit_duration) * 8) +
  383. ((dword)(CAPIDTMF_RECV_TIME_GRANULARITY / 2))) / ((dword) CAPIDTMF_RECV_TIME_GRANULARITY));
  384. if (p_state->recv.min_digit_duration <= 1)
  385. p_state->recv.min_digit_duration = 1;
  386. else
  387. (p_state->recv.min_digit_duration)--;
  388. p_state->recv.min_gap_duration =
  389. (word)((((dword) min_gap_duration) * 8) / ((dword) CAPIDTMF_RECV_TIME_GRANULARITY));
  390. if (p_state->recv.min_gap_duration <= 1)
  391. p_state->recv.min_gap_duration = 1;
  392. else
  393. (p_state->recv.min_gap_duration)--;
  394. p_state->recv.state |= CAPIDTMF_RECV_STATE_DTMF_ACTIVE;
  395. }
  396. void capidtmf_recv_disable(t_capidtmf_state *p_state)
  397. {
  398. p_state->recv.state &= ~CAPIDTMF_RECV_STATE_DTMF_ACTIVE;
  399. if (p_state->recv.state == CAPIDTMF_RECV_STATE_IDLE)
  400. capidtmf_recv_init(p_state);
  401. else
  402. {
  403. p_state->recv.cycle_counter = 0;
  404. p_state->recv.current_digit_on_time = 0;
  405. p_state->recv.current_digit_off_time = 0;
  406. p_state->recv.current_digit_value = CAPIDTMF_RECV_NO_DIGIT;
  407. }
  408. }
  409. word capidtmf_recv_indication(t_capidtmf_state *p_state, byte *buffer)
  410. {
  411. word i, j, k, flags;
  412. flags = p_state->recv.indication_state ^ p_state->recv.indication_state_ack;
  413. p_state->recv.indication_state_ack ^= flags & CAPIDTMF_RECV_INDICATION_DIGIT;
  414. if (p_state->recv.digit_write_pos != p_state->recv.digit_read_pos)
  415. {
  416. i = 0;
  417. k = p_state->recv.digit_write_pos;
  418. j = p_state->recv.digit_read_pos;
  419. do
  420. {
  421. buffer[i++] = p_state->recv.digit_buffer[j];
  422. j = (j == CAPIDTMF_RECV_DIGIT_BUFFER_SIZE - 1) ? 0 : j + 1;
  423. } while (j != k);
  424. p_state->recv.digit_read_pos = k;
  425. return (i);
  426. }
  427. p_state->recv.indication_state_ack ^= flags;
  428. return (0);
  429. }
  430. #define CAPIDTMF_RECV_WINDOWED_SAMPLES 32
  431. void capidtmf_recv_block(t_capidtmf_state *p_state, byte *buffer, word length)
  432. {
  433. byte result_digit;
  434. word sample_number, cycle_counter, n, i;
  435. word low_peak, high_peak;
  436. dword lo, hi;
  437. byte *p;
  438. short *q;
  439. byte goertzel_result_buffer[CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT];
  440. short windowed_sample_buffer[CAPIDTMF_RECV_WINDOWED_SAMPLES];
  441. if (p_state->recv.state & CAPIDTMF_RECV_STATE_DTMF_ACTIVE)
  442. {
  443. cycle_counter = p_state->recv.cycle_counter;
  444. sample_number = 0;
  445. while (sample_number < length)
  446. {
  447. if (cycle_counter < CAPIDTMF_RECV_ACCUMULATE_CYCLES)
  448. {
  449. if (cycle_counter == 0)
  450. {
  451. for (i = 0; i < CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT; i++)
  452. {
  453. p_state->recv.goertzel_buffer[0][i] = 0;
  454. p_state->recv.goertzel_buffer[1][i] = 0;
  455. }
  456. }
  457. n = CAPIDTMF_RECV_ACCUMULATE_CYCLES - cycle_counter;
  458. if (n > length - sample_number)
  459. n = length - sample_number;
  460. if (n > CAPIDTMF_RECV_WINDOWED_SAMPLES)
  461. n = CAPIDTMF_RECV_WINDOWED_SAMPLES;
  462. p = buffer + sample_number;
  463. q = capidtmf_recv_window_function + cycle_counter;
  464. if (p_state->ulaw)
  465. {
  466. for (i = 0; i < n; i++)
  467. {
  468. windowed_sample_buffer[i] =
  469. (short)((capidtmf_expand_table_ulaw[p[i]] * ((long)(q[i]))) >> 15);
  470. }
  471. }
  472. else
  473. {
  474. for (i = 0; i < n; i++)
  475. {
  476. windowed_sample_buffer[i] =
  477. (short)((capidtmf_expand_table_alaw[p[i]] * ((long)(q[i]))) >> 15);
  478. }
  479. }
  480. capidtmf_recv_goertzel_coef_table[CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT - 1] = CAPIDTMF_RECV_FUNDAMENTAL_OFFSET;
  481. capidtmf_goertzel_loop(p_state->recv.goertzel_buffer[0],
  482. capidtmf_recv_goertzel_coef_table, windowed_sample_buffer, n);
  483. cycle_counter += n;
  484. sample_number += n;
  485. }
  486. else
  487. {
  488. capidtmf_goertzel_result(p_state->recv.goertzel_buffer[0],
  489. capidtmf_recv_goertzel_coef_table);
  490. for (i = 0; i < CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT; i++)
  491. {
  492. lo = (dword)(p_state->recv.goertzel_buffer[0][i]);
  493. hi = (dword)(p_state->recv.goertzel_buffer[1][i]);
  494. if (hi != 0)
  495. {
  496. n = capidtmf_dword_leading_zeroes(hi);
  497. hi = (hi << n) | (lo >> (32 - n));
  498. }
  499. else
  500. {
  501. n = capidtmf_dword_leading_zeroes(lo);
  502. hi = lo << n;
  503. n += 32;
  504. }
  505. n = 195 - 3 * n;
  506. if (hi >= 0xcb300000L)
  507. n += 2;
  508. else if (hi >= 0xa1450000L)
  509. n++;
  510. goertzel_result_buffer[i] = (byte) n;
  511. }
  512. low_peak = DSPDTMF_RX_SENSITIVITY_LOW_DEFAULT;
  513. result_digit = CAPIDTMF_RECV_NO_DIGIT;
  514. for (i = 0; i < CAPIDTMF_LOW_GROUP_FREQUENCIES; i++)
  515. {
  516. if (goertzel_result_buffer[i] > low_peak)
  517. {
  518. low_peak = goertzel_result_buffer[i];
  519. result_digit = (byte) i;
  520. }
  521. }
  522. high_peak = DSPDTMF_RX_SENSITIVITY_HIGH_DEFAULT;
  523. n = CAPIDTMF_RECV_NO_DIGIT;
  524. for (i = CAPIDTMF_LOW_GROUP_FREQUENCIES; i < CAPIDTMF_RECV_BASE_FREQUENCY_COUNT; i++)
  525. {
  526. if (goertzel_result_buffer[i] > high_peak)
  527. {
  528. high_peak = goertzel_result_buffer[i];
  529. n = (i - CAPIDTMF_LOW_GROUP_FREQUENCIES) << 2;
  530. }
  531. }
  532. result_digit |= (byte) n;
  533. if (low_peak + DSPDTMF_RX_HIGH_EXCEEDING_LOW_DEFAULT < high_peak)
  534. result_digit = CAPIDTMF_RECV_NO_DIGIT;
  535. if (high_peak + DSPDTMF_RX_LOW_EXCEEDING_HIGH_DEFAULT < low_peak)
  536. result_digit = CAPIDTMF_RECV_NO_DIGIT;
  537. n = 0;
  538. for (i = 0; i < CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT; i++)
  539. {
  540. if ((((short)(low_peak - goertzel_result_buffer[i] - capidtmf_recv_guard_snr_low_table[i])) < 0)
  541. || (((short)(high_peak - goertzel_result_buffer[i] - capidtmf_recv_guard_snr_high_table[i])) < 0))
  542. {
  543. n++;
  544. }
  545. }
  546. if (n != 2)
  547. result_digit = CAPIDTMF_RECV_NO_DIGIT;
  548. if (result_digit == CAPIDTMF_RECV_NO_DIGIT)
  549. {
  550. if (p_state->recv.current_digit_on_time != 0)
  551. {
  552. if (++(p_state->recv.current_digit_off_time) >= p_state->recv.min_gap_duration)
  553. {
  554. p_state->recv.current_digit_on_time = 0;
  555. p_state->recv.current_digit_off_time = 0;
  556. }
  557. }
  558. else
  559. {
  560. if (p_state->recv.current_digit_off_time != 0)
  561. (p_state->recv.current_digit_off_time)--;
  562. }
  563. }
  564. else
  565. {
  566. if ((p_state->recv.current_digit_on_time == 0)
  567. && (p_state->recv.current_digit_off_time != 0))
  568. {
  569. (p_state->recv.current_digit_off_time)--;
  570. }
  571. else
  572. {
  573. n = p_state->recv.current_digit_off_time;
  574. if ((p_state->recv.current_digit_on_time != 0)
  575. && (result_digit != p_state->recv.current_digit_value))
  576. {
  577. p_state->recv.current_digit_on_time = 0;
  578. n = 0;
  579. }
  580. p_state->recv.current_digit_value = result_digit;
  581. p_state->recv.current_digit_off_time = 0;
  582. if (p_state->recv.current_digit_on_time != 0xffff)
  583. {
  584. p_state->recv.current_digit_on_time += n + 1;
  585. if (p_state->recv.current_digit_on_time >= p_state->recv.min_digit_duration)
  586. {
  587. p_state->recv.current_digit_on_time = 0xffff;
  588. i = (p_state->recv.digit_write_pos == CAPIDTMF_RECV_DIGIT_BUFFER_SIZE - 1) ?
  589. 0 : p_state->recv.digit_write_pos + 1;
  590. if (i == p_state->recv.digit_read_pos)
  591. {
  592. trace(dprintf("%s,%d: Receive digit overrun",
  593. (char *)(FILE_), __LINE__));
  594. }
  595. else
  596. {
  597. p_state->recv.digit_buffer[p_state->recv.digit_write_pos] = result_digit;
  598. p_state->recv.digit_write_pos = i;
  599. p_state->recv.indication_state =
  600. (p_state->recv.indication_state & ~CAPIDTMF_RECV_INDICATION_DIGIT) |
  601. (~p_state->recv.indication_state_ack & CAPIDTMF_RECV_INDICATION_DIGIT);
  602. }
  603. }
  604. }
  605. }
  606. }
  607. cycle_counter = 0;
  608. sample_number++;
  609. }
  610. }
  611. p_state->recv.cycle_counter = cycle_counter;
  612. }
  613. }
  614. void capidtmf_init(t_capidtmf_state *p_state, byte ulaw)
  615. {
  616. p_state->ulaw = ulaw;
  617. capidtmf_recv_init(p_state);
  618. }
  619. /*---------------------------------------------------------------------------*/