DTMF decoding in Java using Goertzel algorithm
I am trying to decode DTMF coded wav file in Java. I am using
http://goo.gl/CTY8D8 as reference. This code may detect the same DTMF
character multiple times (depending on binsize and frequency).
The Java code is not giving the same output as the Python version. Did I
do something wrong with datatype choices or did my implementation mess up?
What is a reliable logic to remove the duplicates and detect simultaneous
same key presses (like *1223# or *111#)?
The python version works just fine for almost all the wav files I tried with.
public void init(int samplerate) {
double normalized_freq;
for (int i = 0; i < 8; i++) {
this.totalPower[i] = 0.0;
this.N[i] = 0.0;
this.Q1[i] = 0.0;
this.Q2[i] = 0.0;
normalized_freq = dtmf_freq[i] / samplerate;
this.coeff[i] = 2.0 * Math.cos(2.0 * Math.PI * normalized_freq);
this.real[i] = 0.0;
this.imag[i] = 0.0;
}
}
public String get_number(double[] freqs) {
double hifreq = 0.0;
double hifreq_v = 0.0;
for (int f = 0; f < 4; f++) {
if (freqs[f] > hifreq_v) {
hifreq_v = freqs[f];
hifreq = dtmf_freq[f];
}
}
double lofreq = 0.0;
double lofreq_v = 0.0;
for (int f = 4; f < 8; f++) {
if (freqs[f] > lofreq_v) {
lofreq_v = freqs[f];
lofreq = dtmf_freq[f];
}
}
if (lofreq == 697.0) {
if (hifreq == 1209.0) {
return "1";
} else if (hifreq == 1336.0) {
return "2";
} else if (hifreq == 1477.0) {
return "3";
} else if (hifreq == 1633.0) {
return "A";
}
} else if (lofreq == 770.0) {
if (hifreq == 1209.0) {
return "4";
} else if (hifreq == 1336.0) {
return "5";
} else if (hifreq == 1477.0) {
return "6";
} else if (hifreq == 1633.0) {
return "B";
}
} else if (lofreq == 852.0) {
if (hifreq == 1209.0) {
return "7";
} else if (hifreq == 1336.0) {
return "8";
} else if (hifreq == 1477.0) {
return "9";
} else if (hifreq == 1633.0) {
return "C";
}
} else if (lofreq == 941.0) {
if (hifreq == 1209.0) {
return "*";
} else if (hifreq == 1336.0) {
return "0";
} else if (hifreq == 1477.0) {
return "#";
} else if (hifreq == 1633.0) {
return "D";
}
}
return ".";
}
public String run(short sample){
double [] freqs = new double[8];
double Q0, power;
for (int i=0; i<8; i++){
Q0 = (double) sample + (this.coeff[i] * this.Q1[i]) - this.Q2[i];
this.Q2[i] = this.Q1[i];
this.Q1[i] = Q0;
this.N[i] += 1;
power = (this.Q1[i] * this.Q1[i]) + (this.Q2[i] * this.Q2[i])
- (this.coeff[i] * this.Q1[i] * this.Q2[i]);
this.totalPower[i] = (double) sample*sample;
if(0 == this.totalPower[i]){
this.totalPower[i] = 1;
}
freqs[i] = power / this.totalPower[i] / this.N[i];
}
return get_number(freqs);
}
public String processAudio(File file) {
// File objects
WavFile audioFile = null;
FileInputStream fis = null;
// Wavefile params
int binsize;
int binsplit;
long samplerate;
// Arrays to hold raw data
short[] left = { 0 };
short[] right = { 0 };
short[] frames = { 0 };
String value = " ";
String prevvalue = " ";
String dtmf_string = " ";
int counter = 0;
try {
fis = new FileInputStream(file);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
audioFile = WavFile.openWavFile(fis);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (WavFileException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
samplerate = audioFile.getSampleRate();
init((int) samplerate);
int bufferSize = (int) (audioFile.getNumChannels() * audioFile
.getNumFrames());
byte[] data = new byte[bufferSize];
try {
while (fis.read(data) != -1) {
ShortBuffer sbuf = ByteBuffer.wrap(data)
.order(ByteOrder.LITTLE_ENDIAN).asShortBuffer();
frames = new short[sbuf.capacity()];
sbuf.get(frames);
}
if (2 == audioFile.getNumChannels()) {
left = new short[frames.length / 2];
right = new short[frames.length / 2];
for (int i = 0, j = 0; i < frames.length; i += 2, j++) {
left[j] = frames[i];
}
for (int i = 1, j = 0; i < frames.length; i += 2, j++) {
right[j] = frames[i];
}
} else {
left = frames.clone();
right = left.clone();
}
binsize = 400;
binsplit = 4;
for (int i=0; i<(left.length - binsize); i += binsize/binsplit){
init((int)samplerate);
for (int j=0; j<i+binsize; j++){
value = run(left[j]);
}
if (value == prevvalue){
counter++;
if (10 == counter){
dtmf_string += value;
}
}else{
counter=0;
prevvalue = value;
}
}
return dtmf_string;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "NO DTMF STRING FOUND";
}
No comments:
Post a Comment