gpt4 book ai didi

Java (J2SE) DTMF 音调检测

转载 作者:行者123 更新时间:2023-12-01 13:06:41 31 4
gpt4 key购买 nike

我正在尝试执行以下操作

  • 我正在使用我的 java 应用程序给另一个人打电话(已经完成并且工作正常)。
  • 然后我正在播放录音,例如“请按 1 以继续用英语”(已经完成并且工作正常)。
  • 现在我想检测那个人按下一个,根据我在谷歌搜索中的研究,我知道这可以使用 DTMF 来完成。如果这个人按下 1,我想根据我的条件执行操作。

  • 我的问题是如何在 java (J2SE) 中使用 DTMF 检测该数字。我正在使用 ZTE USB 加密狗调用电话。拨号、挂断等控制都是通过AT指令+Java IO实现的。

    这是我的示例代码,但它每次都没有给出正确的拨号号码及其循环。
    public class zxczczz extends javax.swing.JFrame {

    /**
    * Creates new form zxczczz
    */
    public zxczczz() {
    initComponents();
    }
    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[2048];
    static final char FRAME_SIZE = 160;
    AudioFormat format = getAudioFormat();
    int[] buf;
    public boolean wait = false;
    static boolean continueParsingDtmf = false;

    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 class DtmfCapture extends Thread {

    public void run() {
    continueParsingDtmf = true;
    try {

    DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
    TargetDataLine out = (TargetDataLine) AudioSystem.getLine(info);

    out.open(format);
    out.drain();
    out.start();
    int count = 0;

    while (continueParsingDtmf) {
    byte[] buffer = new byte[2048];
    //grab audio data
    count = out.read(buffer, 0, buffer.length);
    if (count >= 0) {
    zxczczz.DecodeDtmf dtmf = new zxczczz.DecodeDtmf(buffer);
    if (!wait) {

    dtmf.start(); //look for dtmf
    // System.out.println("aaaaaa");
    Thread.sleep(100);
    } else {
    Thread.sleep(1000);// 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;
    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]);
    }
    // System.out.println("aa="+goertzelValues);

    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;
    }
    // System.out.println("low = "+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;
    }
    // System.out.println("aaa="+dtmfBoard[lowFreq][highFreq]);
    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);
    //System.out.println(WNk);
    return Math.abs(vkn - WNk * vkn1);

    }
    }

    请帮我。

    最佳答案

    我正在为 ActionScript 中的 DTMF 检测寻找相同的东西
    我发现了一些东西,也许你可以用 java 重新编码

      package {
    import flash.utils.ByteArray;

    public class DTMFprocessor
    {

    /*
    The following constants are used to find the DTMF tones. The COL1 is the column Hz that we
    are searching for, and the COL2 is the row Hz. The DTMF_LAYOUT is the order that the cols and
    rows intersect at.
    */

    private static const COL1:Array = [697, 770, 852, 941];
    private static const COL2:Array = [1209, 1336, 1477, 1633];
    private static const DTMF_LAYOUT:Array = [ ["1","2","3","A"] ,
    ["4","5","6","B"] ,
    ["7","8","9","C"] ,
    ["*","0","#","D"] ];

    private var sampleRate:int;
    private var lastFound:String = "";

    public var DTMFToneSensitivity:int = 15;

    /**
    * DTMF Processor Constructor
    *
    * @param sampleRate This is the sample rate, in frames per second that the application is operating in.
    *
    */
    public function DTMFprocessor(sampleRate:int = 44100)
    {
    this.sampleRate = sampleRate;
    }

    /**
    * Generates DTMF byteArrays that can be played by the Sound() object.
    *
    * @param length length, in ms that the tone will be generated for.
    * @param tone the string representing the tone that will be generated [0-9, A-D, *, #]
    * @return the byteArray that contains the DTMF tone.
    *
    */
    public function generateDTMF(length:int, tone:String):ByteArray
    {
    var mySound:ByteArray = new ByteArray();
    var neededSamples:int = Math.floor(length * sampleRate / 1000);
    var mySampleCol:Number = 0;
    var mySampleRow:Number = 0;

    var hz:Object = findDTMF(tone.charAt(0));

    for (var i:int = 0; i < neededSamples; i++)
    {
    mySampleCol = Math.sin(i * hz.col * Math.PI * 2 / sampleRate) * 0.5;
    mySampleRow = Math.sin(i * hz.row * Math.PI * 2 / sampleRate) * 0.5;
    mySound.writeFloat(mySampleRow + mySampleCol);

    }
    return mySound;
    }

    /**
    * Searches a ByteArray (from a Sound() object) for a valid DTMF tone.
    *
    * @param tone ByteArray that should contain a valid DTMF tone.
    * @return string representation of DTMF tones. Will return a blank string ('') if nothing is found
    *
    */
    public function searchDTMF(tone:ByteArray):String
    {
    var position:int = 0;
    var charFound:String = "";

    // seed blank values for strongest tone to be found in the byteArray
    var maxCol:int = -1;
    var maxColValue:int = 0;
    var maxRow:int = -1;
    var maxRowValue:int = 0;
    var foundTones:String = "";

    // reset the byteArray to the beginning, should we have gotten it in any other state.
    tone.position = position;

    // break up the byteArray in manageable chunks of 8192 bytes.
    for (var bufferLoop:int =0; bufferLoop < tone.bytesAvailable; bufferLoop =+ 8192)
    {
    position = bufferLoop;

    // search for the column tone.
    for (var col:int = 0; col < 4; col++)
    {
    if (powerDB(goertzel(tone,8192,COL1[col],position)) > maxColValue)
    {
    maxColValue = powerDB(goertzel(tone,8192,COL1[col],position));
    maxCol = col;
    }
    }

    // search for the row tone.
    for (var row:int = 0; row < 4; row++)
    {
    if (powerDB(goertzel(tone,8192,COL2[row],position)) > maxRowValue)
    {
    maxRowValue = powerDB(goertzel(tone,8192,COL2[row],position));
    maxRow = row;
    }
    }

    // was there enough strength in both the column and row to be valid?
    if ((maxColValue < DTMFToneSensitivity) || (maxRowValue < DTMFToneSensitivity))
    {
    charFound = "";
    }
    else
    {
    charFound = DTMF_LAYOUT[maxCol][maxRow];
    }

    if (lastFound != charFound)
    {
    trace("Found DTMF Tone:",charFound);
    lastFound = charFound; // this is so we don't have duplicates.
    foundTones = foundTones + lastFound;
    }

    }
    return foundTones;
    }

    /**
    * Converts amplitude to dB (power).
    *
    * @param value amplitude value
    * @return dB
    *
    */
    private function powerDB(value:Number):Number
    {
    return 20 * Math.log(Math.abs(value))*Math.LOG10E;
    }

    /**
    * This function returns the amplitude of the a seeked wave in the buffer.
    *
    * @param buffer the byteArray that is being searched.
    * @param bufferSize the size of the buffer that we wish to search.
    * @param frequency the frequency (in Hz) that we are searching for.
    * @param bufferPos the starting point that we want to search from.
    * @return amplitude of the searched frequency, if any.
    *
    */
    private function goertzel(buffer:ByteArray, bufferSize:int, frequency:int, bufferPos:int):Number
    {
    var skn:Number = 0;
    var skn1:Number = 0;
    var skn2:Number = 0;

    buffer.position = bufferPos;

    for (var i:int=0; i < bufferSize; i++)
    {
    skn2 = skn1;
    skn1 = skn;
    if (buffer.bytesAvailable > 0)
    skn = 2 * Math.cos(2 * Math.PI * frequency / sampleRate) * skn1 - skn2 + buffer.readFloat();
    }

    var wnk:Number = Math.exp(-2 * Math.PI * frequency / sampleRate);

    return (skn - wnk * skn1);
    }

    /**
    * Returns the Hz of the string tone that is searched.
    *
    * @param tone character that is being search for
    * @return an untyped object that has col and row properties that contain the Hz of the DTMF tone.
    *
    */
    private function findDTMF(tone:String):Object
    {
    var myDTMF:Object = new Object();

    switch(tone)
    {
    case "1":
    myDTMF.col = COL1[0];
    myDTMF.row = COL2[0];
    break;
    case "2":
    myDTMF.col = COL1[0];
    myDTMF.row = COL2[1];
    break;
    case "3":
    myDTMF.col = COL1[0];
    myDTMF.row = COL2[2];
    break;
    case "A":
    myDTMF.col = COL1[0];
    myDTMF.row = COL2[3];
    break;
    case "4":
    myDTMF.col = COL1[1];
    myDTMF.row = COL2[0];
    break;
    case "5":
    myDTMF.col = COL1[1];
    myDTMF.row = COL2[1];
    break;
    case "6":
    myDTMF.col = COL1[1];
    myDTMF.row = COL2[2];
    break;
    case "B":
    myDTMF.col = COL1[1];
    myDTMF.row = COL2[3];
    break;
    case "7":
    myDTMF.col = COL1[2];
    myDTMF.row = COL2[0];
    break;
    case "8":
    myDTMF.col = COL1[2];
    myDTMF.row = COL2[1];
    break;
    case "9":
    myDTMF.col = COL1[2];
    myDTMF.row = COL2[2];
    break;
    case "C":
    myDTMF.col = COL1[2];
    myDTMF.row = COL2[3];
    break;
    case "*":
    myDTMF.col = COL1[3];
    myDTMF.row = COL2[0];
    break;
    case "0":
    myDTMF.col = COL1[3];
    myDTMF.row = COL2[1];
    break;
    case "#":
    myDTMF.col = COL1[3];
    myDTMF.row = COL2[2];
    break;
    case "D":
    myDTMF.col = COL1[3];
    myDTMF.row = COL2[2];
    break;
    default:
    myDTMF.col = 0;
    myDTMF.row = 0;
    }
    return myDTMF;
    }
    }
    }

    关于Java (J2SE) DTMF 音调检测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17539366/

    31 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com