public  class DTMF {
 
  // s: sound object (for sampling rate)
  // f: frequency of note
  // a: amplitude (volume) of note
  // i: index of note's slot
  private static int generateNoteSample(Sound s, double f, int a, int i) {
    double realSlotTime = (i + 0.5)/s.getSamplingRate() ;
    double angleRadians = 2 * Math.PI * f * realSlotTime  ;
    double sineValue    = Math.sin(angleRadians) ;
    return (int)Math.round(sineValue*a) ;
  }
  
  private static final double[] colDTMF = { 1209.0, 1336.0, 1477.0, 1633.0 } ;
  private static final double[] rowDTMF = {  697.0,  770.0,  852.0,  941.0 } ;
  
  private static Sound makePhoneKey(int i) {
    i = i%10 ;
    int row, col ;
    if (i==0) {
      row = 3; 
      col = 1;
    } else {
      row = (i-1)/3 ;
      col = (i-1)%3 ;
    }
    return makePhoneKey(row, col) ;
  }

  private static Sound makePhoneKey(char c) {
    if (c == '*') {
      return makePhoneKey(3, 0) ;
    } else if (c == '#') {
      return makePhoneKey(3, 2) ;
    } else if ('A' <= c && c <= 'D') {
      return makePhoneKey(c - 'A', 4) ;
    } else {
      return makePhoneKey(c - '0') ;
    }
  }
  
  private static Sound makePhoneKey(int row, int col) {
    // Required to be at least 70 msec
    Sound tones = new Sound(8000) ;
    if (row < 0 || row >= 4 || col < 0 || col >= 4) {
      return tones ;
    }
    int noteMax = 20000 ;
    for (int p=0; p< tones.getNumSamples() ; ++p) {
      int sampValue = (generateNoteSample(tones, rowDTMF[row], noteMax, p)
		       + generateNoteSample(tones, colDTMF[col], noteMax, p)
		       + 1) / 2 ;
      tones.setSampleValueAt(p, sampValue) ;
    }    
    return tones ;
  }

  
  public static void main(String[] args) {
    long phoneNumber   = 8282322275l ;
    int  digitSelector = 1000000000 ;
    while (phoneNumber != 0) {
      int nextKey = (int)(phoneNumber/digitSelector) ;
      try {Thread.sleep(400) ;} catch(Exception e) { }
      System.out.println(nextKey) ;
      makePhoneKey(nextKey).blockingPlay() ;
      phoneNumber   = phoneNumber   % digitSelector ;
      digitSelector = digitSelector / 10 ;
    }
    try {Thread.sleep(1000) ;} catch(Exception e) { } // magic
    System.out.println('#') ;
    makePhoneKey('#').blockingPlay() ;
  }
}