我正在尝试执行以下操作
我正在使用我的 java 应用程序给另一个人打电话(已经完成并且工作正常)。
然后我正在播放录音,例如“请按 1 以继续用英语”(已经完成并且工作正常)。
现在我想检测那个人按下一个,根据我在谷歌搜索中的研究,我知道这可以使用 DTMF 来完成。如果这个人按下 1,我想根据我的条件执行操作。
我的问题是如何在 java (J2SE) 中使用 DTMF 检测该数字。我正在使用 ZTE USB 加密狗拨打电话。拨号、挂断等控制都是通过AT指令+Java IO实现的。
package tracenumber;
import java.io.IOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.TargetDataLine;
public class DTMFDetect {
/**
* @param args
*/
float[] lowFreq = new float[]{697.0F, 770.0F, 852.0F, 941.0F};
float[] highFreq = new float[]{1209.0F, 1336.0F, 1477.0F, 1633.0F};
float[] dtmfTones = new float[]{697.0F, 770.0F, 852.0F, 941.0F, 1209.0F, 1336.0F, 1477.0F, 1633.0F};
int dtmfBoard[][] = { { 1, 2, 3, 12 }, { 4, 5, 6, 13 }, { 7, 8, 9, 14 }, { 10, 0, 11, 15} };
//byte[] buffer = new byte[2000];
static final char FRAME_SIZE = 160;
AudioFormat format = getAudioFormat();
//int[] buf;
public boolean wait = false;
static boolean continueParsingDtmf = false;
public DTMFDetect()
{
}
public AudioFormat getAudioFormat()
{
// float sampleRate = 8000.0F;
float sampleRate = 44100.0F;
//int sampleSizeInBits = 16;
int sampleSizeInBits = 8;
int channels = 1;
boolean signed = true;
boolean bigEndian = true;
return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed, bigEndian);
}
public static void main(String args[]) throws LineUnavailableException, IOException
{
// start seaching for audio signals
new DtmfCapture().start();
// decode for a minute
try { Thread.sleep(60000);
} catch (Exception e){
}
continueParsingDtmf = false;
}
public class DtmfCapture extends Thread {
public void run() {
continueParsingDtmf = true;
try {
int tone = 0;
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
TargetDataLine out= (TargetDataLine) AudioSystem.getLine(info);
int[] buf ;
out.open(format);
out.drain();
out.start();
int count = 0;
while (continueParsingDtmf) {
byte[] buffer = new byte[2000];
//grab audio data
count = out.read(buffer,0,buffer.length);
if(count > 0){
DecodeDtmf dtmf = new DecodeDtmf(buffer);
if (!wait){
dtmf.start(); //look for dtmf
Thread.sleep(100);
} else
{
Thread.sleep(4000); // wait before searching again
System.out.println(System.currentTimeMillis());
wait = false;
}
}
}
out.close();
} catch(Exception e){
e.printStackTrace();
}
}
}
public class DecodeDtmf extends Thread {
//
byte[] buffer;
DecodeDtmf(byte[] buffer) {
this.buffer = buffer;
}
public void run() {
int[] buf;
buf = new int[buffer.length/2];
for(int j = 0; j<buffer.length/2-1; j++)
{
buf[j] = (int) ((buffer[j*2+1] & 0xFF) + (buffer[j*2] << 8));
}
int tone = findDTMF(buf);
if (tone >=0)
{ wait = true;
//System.out.print(time);
if ( tone <10)
{System.out.println(" THE TONE IS : " + tone);
}
if (tone ==12)
{ System.out.println(" THE TONE IS : A" );
}
if (tone ==13)
{ System.out.println(" THE TONE IS : B" );
}
if (tone ==14)
{ System.out.println(" THE TONE IS : C" );
}
if (tone ==15)
{ System.out.println(" THE TONE IS : D" );
}
if (tone ==10)
{ System.out.println(" THE TONE IS : *" );
}
if (tone ==11)
{ System.out.println(" THE TONE IS : #" );
}
}
}
/*
Check if sample has dtmf tone
*/
public int findDTMF(int[] samples)
{
double[] goertzelValues = new double[8];
double lowFreqValue = 0;
int lowFreq = 0;
double sumLow = 0;
double highFreqValue = 0;
int highFreq = 0;
double sumHigh = 0;
for(int i = 0; i<8; i++)
{
goertzelValues[i] = goertzel(samples,dtmfTones[i]);
}
for(int i = 0; i<4; i++) // Find st?rste low frequency
{
sumLow += goertzelValues[i]; // Sum til signal-test
if(goertzelValues[i] > lowFreqValue)
{
lowFreqValue = goertzelValues[i];
lowFreq = i;
}
}
for(int i = 4; i<8; i++) // Find st?rste high frequency
{
sumHigh += goertzelValues[i]; // Sum til signal-test
if(goertzelValues[i] > highFreqValue)
{
highFreqValue = goertzelValues[i];
highFreq = i-4;
}
}
if(lowFreqValue < sumLow/2 || highFreqValue < sumHigh/2) // Test signalstyrke
{
return -1;
}
return dtmfBoard[lowFreq][highFreq]; // Returner DTMF tone
}
}
public double goertzel(int[] samples, float freq)
{
double vkn = 0;
double vkn1 = 0;
double vkn2 = 0;
for(int j = 0; j<samples.length -1; j++)
{
vkn2 = vkn1;
vkn1 = vkn;
vkn = 2 * Math.cos(2 * Math.PI * (freq * samples.length / format.getSampleRate() ) / samples.length) * vkn1 - vkn2 + samples[j];
}
double WNk = Math.exp(-2 * Math.PI * (freq * samples.length / format.getSampleRate() ) / samples.length);
return Math.abs(vkn - WNk * vkn1);
}
}