4 * Copyright by Andreas Eversberg (jolly@eversberg.eu)
5 * based on different decoders such as ISDN4Linux
6 * copyright by Karsten Keil
8 * This software may be used and distributed according to the terms
9 * of the GNU General Public License, incorporated herein by reference.
14 #include "ss5_decode.h"
16 /* enable level debugging */
17 //#define DEBUG_LEVELS
19 #define NCOEFF 8 /* number of frequencies to be analyzed */
21 #define MIN_DB 0.01995262 /* -17 db */
22 #define DIFF_DB 0.2 // 0.31622777 /* -5 db */
23 #define SNR 1.3 /* noise may not exceed signal by that factor */
25 /* For DTMF recognition:
26 * 2 * cos(2 * PI * k / N) precalculated for all k
28 static signed long long cos2pik[NCOEFF] =
30 /* k = 2*cos(2*PI*f/8000), k << 15
31 * 700, 900, 1100, 1300, 1500, 1700, 2400, 2600 */
32 55879, 49834, 42562, 34242, 25080, 15299, -20252, -29753
35 /* detection matrix for two frequencies */
36 static char decode_two[8][8] =
38 {' ', '1', '2', '4', '7', '*', ' ', ' '}, /* * = code 11 */
39 {'1', ' ', '3', '5', '8', '#', ' ', ' '}, /* # = code 12 */
40 {'2', '3', ' ', '6', '9', 'a', ' ', ' '}, /* a = KP1 */
41 {'4', '5', '6', ' ', '0', 'b', ' ', ' '}, /* b = KP2 */
42 {'7', '8', '9', '0', ' ', 'c', ' ', ' '}, /* c = ST */
43 {'*', '#', 'a', 'b', 'c', ' ', ' ', ' '},
44 {' ', ' ', ' ', ' ', ' ', ' ', ' ', 'C'}, /* C = 2600+2400 */
45 {' ', ' ', ' ', ' ', ' ', ' ', 'C', ' '}
48 static char decode_one[8] =
49 {' ', ' ', ' ', ' ', ' ', ' ', 'A', 'B'}; /* A = 2400, B = 2600 */
51 * calculate the coefficients of the given sample and decode
54 char ss5_decode(unsigned char *data, int len)
56 signed short buf[len];
57 signed long sk, sk1, sk2, low, high;
60 double result[NCOEFF], power, noise, snr;
61 signed long long cos2pik_;
65 for (i = 0; i < len; i++)
66 buf[i] = audio_law_to_s32[*data++];
68 /* now we have a full buffer of signed long samples - we do goertzel */
69 for (k = 0; k < NCOEFF; k++) {
73 cos2pik_ = cos2pik[k];
74 for (n = 0; n < len; n++) {
75 sk = ((cos2pik_*sk1)>>15) - sk2 + buf[n];
81 if (sk > 32767 || sk < -32767 || sk2 > 32767 || sk2 < -32767)
82 PERROR("Tone-Detection overflow\n");
83 /* compute |X(k)|**2 */
86 (((cos2pik[k] * sk) >> 15) * sk2) +
88 ) / len / 62; /* level of 1 is 0 db*/
91 /* now we do noise level calculation */
94 for (n = 0; n < len; n++) {
101 noise = ((double)(high-low) / 65536.0);
103 /* find the two loudest frequencies + one less lower frequency to detect noise */
105 for (i = 0; i < NCOEFF; i++) {
106 if (result[i] > power) {
112 for (i = 0; i < NCOEFF; i++) {
113 if (i != f1 && result[i] > power) {
120 /* check one frequency */
121 if (result[f1] > MIN_DB /* must be at least -17 db */
122 && result[f1]*SNR > noise) { /* */
123 digit = decode_one[f1];
125 snr = result[f1] / noise;
127 /* check two frequencies */
128 if (result[f1] > MIN_DB && result[f2] > MIN_DB /* must be at lease -17 db */
129 && result[f1]*DIFF_DB <= result[f2] /* f2 must be not less than 5 db below f1 */
130 && (result[f1]+result[f2])*SNR > noise) { /* */
131 digit = decode_two[f1][f2];
133 snr = (result[f1]+result[f2]) / noise;
139 for (i = 0; i < NCOEFF; i++)
140 printf("%d:%3d %c ", i, (int)(result[i]*100), (f1==i || f2==i)?'*':' ');
141 printf("N:%3d digit:%c snr=%3d\n", (int)(noise*100), digit, (int)(snr*100));
142 if (result[f1]*DIFF_DB <= result[f2]) /* f2 must be not less than 5 db below f1 */
150 void ss5_test_decode(void)
157 unsigned char buffer[SS5_DECODER_NPOINTS];
158 for (i = 0; i < 4000; i += 10) {
159 phase = 2.0 * 3.14159265 * i / 8000.0;
160 for (j = 0; j < SS5_DECODER_NPOINTS; j++) {
161 sample = sin(phase * j) * 1000;
162 buffer[j] = audio_s16_to_law[sample & 0xffff];
164 printf("FRQ:%04d:", i);
165 ss5_decode(buffer, SS5_DECODER_NPOINTS);