为什么此代码无法正确检测DTMF音调?

时间:2013-05-13 05:48:46

标签: java javasound dtmf

我正在尝试检测我机器上正在播放的DTMF音调。我有一个我在网站上找到的另一个人的代码。我根据自己的需要重新安排了代码。一切看起来都不错,但即使没有播放,代码也会检测音调!

我在这里做错了什么?这段代码使用Goertzel算法来检测DTMF音调。


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 
        DtmfCapture dtmfCapture = dtmfDetect.new DtmfCapture();
        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);
        }

}

0 个答案:

没有答案