00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include <qapplication.h>
00016
00017 #include <stdio.h>
00018 #include <stdlib.h>
00019 #include <iostream>
00020 #include <math.h>
00021
00022 using namespace std;
00023
00024 #ifndef WIN32
00025 #include "config.h"
00026 #endif
00027 #include "dtmffilter.h"
00028
00029 #ifndef M_PI
00030 #define M_PI 3.1415926
00031 #endif
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 DtmfFilter::DtmfFilter()
00042 {
00043
00044
00045
00046
00047 filter_697 = new goertzel(218, 697, 8000);
00048 filter_770 = new goertzel(187, 770, 8000);
00049 filter_852 = new goertzel(169, 852, 8000);
00050 filter_941 = new goertzel(204, 941, 8000);
00051 filter_1209 = new goertzel(172, 1209, 8000);
00052 filter_1336 = new goertzel(491, 1336, 8000);
00053 filter_1477 = new goertzel(260, 1477, 8000);
00054
00055 Hits[697] = 0;
00056 Hits[770] = 0;
00057 Hits[852] = 0;
00058 Hits[941] = 0;
00059 Hits[1209] = 0;
00060 Hits[1336] = 0;
00061 Hits[1477] = 0;
00062
00063 Debounce['0'] = 0;
00064 Debounce['1'] = 0;
00065 Debounce['2'] = 0;
00066 Debounce['3'] = 0;
00067 Debounce['4'] = 0;
00068 Debounce['5'] = 0;
00069 Debounce['6'] = 0;
00070 Debounce['7'] = 0;
00071 Debounce['8'] = 0;
00072 Debounce['9'] = 0;
00073 Debounce['*'] = 0;
00074 Debounce['#'] = 0;
00075 }
00076
00077 DtmfFilter::~DtmfFilter()
00078 {
00079 delete filter_697;
00080 delete filter_770;
00081 delete filter_852;
00082 delete filter_941;
00083 delete filter_1209;
00084 delete filter_1336;
00085 delete filter_1477;
00086 }
00087
00088 QChar DtmfFilter::process(short *samples, int length)
00089 {
00090 HitCounter(697, filter_697->process(samples, length));
00091 HitCounter(770, filter_770->process(samples, length));
00092 HitCounter(852, filter_852->process(samples, length));
00093 HitCounter(941, filter_941->process(samples, length));
00094 HitCounter(1209, filter_1209->process(samples, length));
00095 HitCounter(1336, filter_1336->process(samples, length));
00096 HitCounter(1477, filter_1477->process(samples, length));
00097
00098 return CheckAnyDTMF();
00099 }
00100
00101 void DtmfFilter::HitCounter(int Frequency, int numHitsThisSample)
00102 {
00103
00104 if (numHitsThisSample == 0)
00105 Hits[Frequency] = 0;
00106 else
00107 Hits[Frequency] += numHitsThisSample;
00108 }
00109
00110 QChar DtmfFilter::CheckAnyDTMF()
00111 {
00112 unsigned char Match = 0;
00113 QChar key=0;
00114 if (Hits[697] > 0) Match |= 0x01;
00115 if (Hits[770] > 0) Match |= 0x02;
00116 if (Hits[852] > 0) Match |= 0x04;
00117 if (Hits[941] > 0) Match |= 0x08;
00118 if (Hits[1209] > 0) Match |= 0x10;
00119 if (Hits[1336] > 0) Match |= 0x20;
00120 if (Hits[1477] > 0) Match |= 0x40;
00121
00122 Debounce['0'] = (Debounce['0'] << 1) & 0xFF;
00123 Debounce['1'] = (Debounce['1'] << 1) & 0xFF;
00124 Debounce['2'] = (Debounce['2'] << 1) & 0xFF;
00125 Debounce['3'] = (Debounce['3'] << 1) & 0xFF;
00126 Debounce['4'] = (Debounce['4'] << 1) & 0xFF;
00127 Debounce['5'] = (Debounce['5'] << 1) & 0xFF;
00128 Debounce['6'] = (Debounce['6'] << 1) & 0xFF;
00129 Debounce['7'] = (Debounce['7'] << 1) & 0xFF;
00130 Debounce['8'] = (Debounce['8'] << 1) & 0xFF;
00131 Debounce['9'] = (Debounce['9'] << 1) & 0xFF;
00132 Debounce['*'] = (Debounce['*'] << 1) & 0xFF;
00133 Debounce['#'] = (Debounce['#'] << 1) & 0xFF;
00134
00135 switch (Match)
00136 {
00137 default:
00138 return 0;
00139 break;
00140 case 0x11: key = '1'; break;
00141 case 0x12: key = '4'; break;
00142 case 0x14: key = '7'; break;
00143 case 0x18: key = '*'; break;
00144 case 0x21: key = '2'; break;
00145 case 0x22: key = '5'; break;
00146 case 0x24: key = '8'; break;
00147 case 0x28: key = '0'; break;
00148 case 0x41: key = '3'; break;
00149 case 0x42: key = '6'; break;
00150 case 0x44: key = '9'; break;
00151 case 0x48: key = '#'; break;
00152 }
00153
00154
00155 Debounce[key] |= 0x01;
00156 if (Debounce[key] != 1)
00157 return 0;
00158
00159 cout << "DTMF Filter matched " << key << endl;
00160 return key;
00161 }
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172 goertzel::goertzel(int N, float targetFreq, float sampleRate)
00173 {
00174 initialise(N, targetFreq, sampleRate);
00175 }
00176
00177 goertzel::~goertzel()
00178 {
00179 }
00180
00181 void goertzel::checkMatch()
00182 {
00183 float magSquared;
00184 float magnitude;
00185
00186 magSquared = Q1 * Q1 + Q2 * Q2 - Q1 * Q2 * coeff;
00187 magnitude = sqrt(magSquared);
00188
00189
00190
00191 if (magnitude > 500000.0)
00192 Match++;
00193
00194 reset();
00195 }
00196
00197 int goertzel::process(short *samples, int length)
00198 {
00199 Match = 0;
00200 while (length > 0)
00201 {
00202 while ((length > 0) && (countToN < m_N))
00203 {
00204 processOneSample(*samples++);
00205 length--;
00206 countToN++;
00207 }
00208 if (m_N == countToN)
00209 checkMatch();
00210 }
00211 return Match;
00212 }
00213
00214 void goertzel::processOneSample(short sample)
00215 {
00216 float Q0;
00217 Q0 = coeff * Q1 - Q2 + (float)sample;
00218 Q2 = Q1;
00219 Q1 = Q0;
00220 }
00221
00222
00223 void goertzel::reset()
00224 {
00225 Q2=0;
00226 Q1=0;
00227 countToN = 0;
00228 }
00229
00230
00231 void goertzel::initialise(int N, float targetFreq, float sampleRate)
00232 {
00233 int k;
00234 float floatN;
00235 float Omega;
00236
00237 m_N = N;
00238 floatN = (float)N;
00239 k = (int)(0.5 + ((floatN * targetFreq) / sampleRate));
00240 Omega = (2.0 * M_PI * k) / floatN;
00241 sine = sin(Omega);
00242 cosine = cos(Omega);
00243 coeff = 2.0 * cosine;
00244
00245 reset();
00246 }
00247
00248
00249
00250
00251