Showing posts with label Android code sample: ToneGenerator. Show all posts
Showing posts with label Android code sample: ToneGenerator. Show all posts

Tuesday, February 10, 2015

Visible DTMF Piano: Visualizer + ToneGenerator

Last post show a example of Visualizer for MediaPlayer, combine with the DTMF Piano using ToneGenerator, here is a Visible DTMF Piano, using Visualizer + ToneGenerator.

In this example, Visualizer is created with session 0, to make the audio output mix is visualized; permission MODIFY_AUDIO_SETTINGS is needed.



VisualizerView.java, extends View.
package com.example.androidaudiovisualizer;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;

public class VisualizerView extends View {

 private byte[] mBytes;
 private float[] mPoints;
 private Rect mRect = new Rect();
 private Paint mForePaint = new Paint();

 public VisualizerView(Context context) {
  super(context);
  init();
 }

 public VisualizerView(Context context, AttributeSet attrs) {
  super(context, attrs);
  init();
 }

 public VisualizerView(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  init();
 }

 private void init() {
  mBytes = null;
  mForePaint.setStrokeWidth(1f);
  mForePaint.setAntiAlias(true);
  mForePaint.setColor(Color.rgb(0, 128, 255));
 }

 public void updateVisualizer(byte[] bytes) {
  mBytes = bytes;
  invalidate();
 }

 @Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  if (mBytes == null) {
   return;
  }
  if (mPoints == null || mPoints.length < mBytes.length * 4) {
   mPoints = new float[mBytes.length * 4];
  }
  mRect.set(0, 0, getWidth(), getHeight());
  for (int i = 0; i < mBytes.length - 1; i++) {
   mPoints[i * 4] = mRect.width() * i / (mBytes.length - 1);
   mPoints[i * 4 + 1] = mRect.height() / 2
     + ((byte) (mBytes[i] + 128)) * (mRect.height() / 2) / 128;
   mPoints[i * 4 + 2] = mRect.width() * (i + 1) / (mBytes.length - 1);
   mPoints[i * 4 + 3] = mRect.height() / 2
     + ((byte) (mBytes[i + 1] + 128)) * (mRect.height() / 2)
     / 128;
  }
  canvas.drawLines(mPoints, mForePaint);
 }

}

activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.androidaudiovisualizer.MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />
    
    <com.example.androidaudiovisualizer.VisualizerView
        android:id="@+id/myvisualizerview"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />
    
    <GridView
        android:id="@+id/gridView"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:columnWidth="50dp"
        android:gravity="center"
        android:numColumns="3"
        android:stretchMode="columnWidth" >
    </GridView>

</LinearLayout>

MainActivity.java
package com.example.androidaudiovisualizer;

import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.GridView;
import android.media.AudioManager;
import android.media.ToneGenerator;
import android.media.audiofx.Visualizer;
import android.os.Bundle;

/*
 * needed in AndroidManifest.xml
 * android:minSdkVersion="9"
 * uses-permission of "android.permission.RECORD_AUDIO"
 * and "android.permission.MODIFY_AUDIO_SETTINGS"
 * 
 * reference: Android demo example -
 * ApiDemos > Media > AudioTx
 */

public class MainActivity extends ActionBarActivity {

 VisualizerView mVisualizerView;
 GridView DTMFPianoView;
 static final String[] numbers = new String[] { "1", "2", "3", "4", "5",
   "6", "7", "8", "9", "*", "0", "#" };

 static final int[] toneTypes = new int[] { ToneGenerator.TONE_DTMF_1,
   ToneGenerator.TONE_DTMF_2, ToneGenerator.TONE_DTMF_3,
   ToneGenerator.TONE_DTMF_4, ToneGenerator.TONE_DTMF_5,
   ToneGenerator.TONE_DTMF_6, ToneGenerator.TONE_DTMF_7,
   ToneGenerator.TONE_DTMF_8, ToneGenerator.TONE_DTMF_9,
   ToneGenerator.TONE_DTMF_S, ToneGenerator.TONE_DTMF_0, 
   ToneGenerator.TONE_DTMF_P
 };

 private Visualizer mVisualizer;

 int streamType;
 int volume;
 int durationMs;
 ToneGenerator toneGenerator;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  mVisualizerView = (VisualizerView) findViewById(R.id.myvisualizerview);

  initAudio();

  DTMFPianoView = (GridView) findViewById(R.id.gridView);
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(
          this, android.R.layout.simple_list_item_1, numbers);
        
        DTMFPianoView.setAdapter(adapter);
        
        DTMFPianoView.setOnItemClickListener(new OnItemClickListener() {

   @Override
   public void onItemClick(AdapterView<?> parent, View view,
     int position, long id) {
    toneGenerator.startTone(toneTypes[position], durationMs);
    
   }});
        
 }

 @Override
 protected void onPause() {
  super.onPause();
  if (isFinishing()) {
   mVisualizer.release();
  }
 }

 private void initAudio() {

  streamType = AudioManager.STREAM_MUSIC;
  volume = 50;
  durationMs = 500;
  toneGenerator = new ToneGenerator(streamType, volume);

  setupVisualizerFxAndUI();
  mVisualizer.setEnabled(true);

 }

 private void setupVisualizerFxAndUI() {

  // Creating a Visualizer on the output mix (audio session 0)
  // need permission MODIFY_AUDIO_SETTINGS
  mVisualizer = new Visualizer(0);

  mVisualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[1]);
  mVisualizer.setDataCaptureListener(
    new Visualizer.OnDataCaptureListener() {
     public void onWaveFormDataCapture(Visualizer visualizer,
       byte[] bytes, int samplingRate) {
      mVisualizerView.updateVisualizer(bytes);
     }

     public void onFftDataCapture(Visualizer visualizer,
       byte[] bytes, int samplingRate) {
     }
    }, Visualizer.getMaxCaptureRate() / 2, true, false);

 }

}

Permission of "android.permission.RECORD_AUDIO" and "android.permission.MODIFY_AUDIO_SETTINGS" are needed in AndroidManifest.xml.


download filesDownload the files.

Thursday, December 4, 2014

Sound samples generated by android.media.ToneGenerator

This example play tones generated with android.media.ToneGenerator. You can download the APK on bottom of this post.


MainActivity.java
package com.example.androidtonegenerator;

import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import android.content.Context;
import android.media.AudioManager;
import android.media.ToneGenerator;
import android.os.Bundle;

public class MainActivity extends ActionBarActivity {
 
 public class Tone{
  int toneType;
  String toneName;
  String toneDesc;
  
  Tone(int toneType, String toneName, String toneDesc){
   this.toneType= toneType;
   this.toneName = toneName;
   this.toneDesc = toneDesc;
  }

  @Override
  public String toString() {
   return toneName;
  }
  
 }
 
 class ToneArrayAdapter extends ArrayAdapter<Tone> {
  
  Tone[] toneArray;

  public ToneArrayAdapter(Context context, int resource, Tone[] objects) {
   super(context, resource, objects);
   toneArray = objects;
  }

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
   View row = convertView;
   
   if(row==null){
    LayoutInflater inflater = getLayoutInflater();
    row=inflater.inflate(R.layout.row, parent, false); 
   }
   
   
   
   TextView listName =(TextView)row.findViewById(R.id.name);
   listName.setText(
     (String.format("%02d", toneArray[position].toneType))
     + " : " + toneArray[position].toneName);

   TextView listDesc=(TextView)row.findViewById(R.id.desc);
   listDesc.setText(toneArray[position].toneDesc);
   
   return row;
  }
  
 }

 Tone[] tones = new Tone[]{

   new Tone(ToneGenerator.TONE_CDMA_ABBR_ALERT,
     "TONE_CDMA_ABBR_ALERT", 
     "CDMA_ABBR_ALERT tone: 1150Hz+770Hz 400ms ON"),
   new Tone(ToneGenerator.TONE_CDMA_ABBR_INTERCEPT,
     "TONE_CDMA_ABBR_INTERCEPT",
     "CDMA Abbr Intercept tone: 440Hz 250ms ON, 620Hz 250ms ON"),
   new Tone(ToneGenerator.TONE_CDMA_ABBR_REORDER,
     "TONE_CDMA_ABBR_REORDER", 
     "CDMA Abbr Reorder tone: 480Hz+620Hz 250ms ON, 250ms OFF repeated for 8 times"),
   new Tone(ToneGenerator.TONE_CDMA_ALERT_AUTOREDIAL_LITE,
     "NE_CDMA_ALERT_AUTOREDIAL_LITE",
     "CDMA Alert Auto Redial tone: {1245Hz 62ms ON, 659Hz 62ms ON} 3 times, 1245 62ms ON"),
   new Tone(ToneGenerator.TONE_CDMA_ALERT_CALL_GUARD,
     "TONE_CDMA_ALERT_CALL_GUARD", 
     "CDMA ALERT CALL GUARD tone: {1319Hz 125ms ON, 125ms OFF} 3 times"),
   new Tone(ToneGenerator.TONE_CDMA_ALERT_INCALL_LITE,
     "TONE_CDMA_ALERT_INCALL_LITE", 
     "CDMA ALERT INCALL LITE tone: 587Hz 62ms, 784 62ms, 831Hz 62ms, 784Hz 62ms, 1109 62ms, 784Hz 62ms, 831Hz 62ms, 784Hz 62ms"),
   new Tone(ToneGenerator.TONE_CDMA_ALERT_NETWORK_LITE,
     "TONE_CDMA_ALERT_NETWORK_LITE", 
     "CDMA Alert Network Lite tone: 1109Hz 62ms ON, 784Hz 62ms ON, 740Hz 62ms ON 622Hz 62ms ON, 1109Hz 62ms ON"),
   new Tone(ToneGenerator.TONE_CDMA_ANSWER,
     "TONE_CDMA_ANSWER", 
     "CDMA answer tone: silent tone - defintion Frequency 0, 0ms ON, 0ms OFF"),
   new Tone(ToneGenerator.TONE_CDMA_CALLDROP_LITE, 
     "TONE_CDMA_CALLDROP_LITE",
     "CDMA CALLDROP LITE tone: 1480Hz 125ms, 1397Hz 125ms, 784Hz 125ms"),
   new Tone(ToneGenerator.TONE_CDMA_CALL_SIGNAL_ISDN_INTERGROUP,
     "TONE_CDMA_CALL_SIGNAL_ISDN_INTERGROUP", 
     "ISDN Call Signal Intergroup tone: {2091Hz 32ms ON, 2556 64ms ON} 8 times, 2091Hz 32ms ON, 400ms OFF, {2091Hz 32ms ON, 2556Hz 64ms ON} times, 2091Hz 32ms ON, 4s OFF."),
   new Tone(ToneGenerator.TONE_CDMA_CALL_SIGNAL_ISDN_NORMAL,
     "TONE_CDMA_CALL_SIGNAL_ISDN_NORMAL", 
     "ISDN Call Signal Normal tone: {2091Hz 32ms ON, 2556 64ms ON} 20 times, 2091 32ms ON, 2556 48ms ON, 4s OFF"),
   new Tone(ToneGenerator.TONE_CDMA_CALL_SIGNAL_ISDN_PAT3,
     "TONE_CDMA_CALL_SIGNAL_ISDN_PAT3",
     "ISDN Call sign PAT3 tone: silent tone"),
   new Tone(ToneGenerator.TONE_CDMA_CALL_SIGNAL_ISDN_PAT5,
     "TONE_CDMA_CALL_SIGNAL_ISDN_PAT5", 
     "ISDN Pat5 tone: silent tone"),
   new Tone(ToneGenerator.TONE_CDMA_CALL_SIGNAL_ISDN_PAT6,
     "TONE_CDMA_CALL_SIGNAL_ISDN_PAT6", 
     "ISDN Pat6 tone: silent tone"),
   new Tone(ToneGenerator.TONE_CDMA_CALL_SIGNAL_ISDN_PAT7,
     "TONE_CDMA_CALL_SIGNAL_ISDN_PAT7", 
     "ISDN Pat7 tone: silent tone"),
   new Tone(ToneGenerator.TONE_CDMA_CALL_SIGNAL_ISDN_PING_RING,
     "TONE_CDMA_CALL_SIGNAL_ISDN_PING_RING", 
     "ISDN Ping Ring tone: {2091Hz 32ms ON, 2556Hz 64ms ON} 5 times 2091Hz 20ms ON"),
   new Tone(ToneGenerator.TONE_CDMA_CALL_SIGNAL_ISDN_SP_PRI,
     "TONE_CDMA_CALL_SIGNAL_ISDN_SP_PRI",
     "ISDN Call Signal SP PRI tone:{2091Hz 32ms ON, 2556 64ms ON} 4 times 2091Hz 16ms ON, 200ms OFF, {2091Hz 32ms ON, 2556Hz 64ms ON} 4 times, 2091Hz 16ms ON, 200ms OFF"),
   new Tone(ToneGenerator.TONE_CDMA_CONFIRM,
     "TONE_CDMA_CONFIRM",
     "CDMA Confirm tone: 350Hz+440Hz 100ms ON, 100ms OFF repeated for 3 times"),
   new Tone(ToneGenerator.TONE_CDMA_DIAL_TONE_LITE,
     "TONE_CDMA_DIAL_TONE_LITE",
     "CDMA Dial tone : 425Hz continuous"),
   new Tone(ToneGenerator.TONE_CDMA_EMERGENCY_RINGBACK,
     "TONE_CDMA_EMERGENCY_RINGBACK",
     "CDMA EMERGENCY RINGBACK tone: {941Hz 125ms ON, 10ms OFF} 3times 4990ms OFF, REPEAT..."),
   new Tone(ToneGenerator.TONE_CDMA_HIGH_L,
     "TONE_CDMA_HIGH_L",
     "TONE_CDMA_HIGH_L tone: {3700Hz 25ms, 4000Hz 25ms} 40 times 4000ms OFF, Repeat ...."),
   new Tone(ToneGenerator.TONE_CDMA_HIGH_PBX_L,
     "TONE_CDMA_HIGH_PBX_L",
     "CDMA HIGH PBX L: {3700Hz 25ms, 4000Hz 25ms}20 times, 2000ms OFF, REPEAT...."),
   new Tone(ToneGenerator.TONE_CDMA_HIGH_PBX_SLS,
     "TONE_CDMA_HIGH_PBX_SLS",
     "CDMA HIGH PBX SSL tone:{3700Hz 25ms, 4000Hz 25ms} 8 times 200ms OFF, {3700Hz 25ms, 4000Hz 25ms} 16 times, 200ms OFF, {3700Hz 25ms, 4000Hz 25ms} 8 times, 1000ms OFF, REPEAT...."),
   new Tone(ToneGenerator.TONE_CDMA_HIGH_PBX_SS,
     "TONE_CDMA_HIGH_PBX_SS",
     "CDMA HIGH PBX SS tone: {3700Hz 25ms, 4000Hz 25ms} 8 times 200 ms OFF, {3700Hz 25ms 4000Hz 25ms}8 times, 2000ms OFF, REPEAT...."),
   new Tone(ToneGenerator.TONE_CDMA_HIGH_PBX_SSL,
     "TONE_CDMA_HIGH_PBX_SSL",
     "CDMA HIGH PBX SSL tone:{3700Hz 25ms, 4000Hz 25ms} 8 times 200ms OFF, {3700Hz 25ms, 4000Hz 25ms} 8 times, 200ms OFF, {3700Hz 25ms, 4000Hz 25ms} 16 times, 1000ms OFF, REPEAT...."),
   new Tone(ToneGenerator.TONE_CDMA_HIGH_PBX_S_X4,
     "TONE_CDMA_HIGH_PBX_S_X4",
     "CDMA HIGH PBX X S4 tone: {3700Hz 25ms 4000Hz 25ms} 8 times, 200ms OFF, {3700Hz 25ms 4000Hz 25ms} 8 times, 200ms OFF, {3700Hz 25ms 4000Hz 25ms} 8 times, 200ms OFF, {3700Hz 25ms 4000Hz 25ms} 8 times, 800ms OFF, REPEAT..."),
   new Tone(ToneGenerator.TONE_CDMA_HIGH_SLS,
     "TONE_CDMA_HIGH_SLS",
     "CDMA HIGH SLS tone: {3700Hz 25ms, 4000Hz 25ms} 10 times, 500ms OFF, {3700Hz 25ms, 4000Hz 25ms} 20 times, 500ms OFF, {3700Hz 25ms, 4000Hz 25ms} 10 times, 3000ms OFF, REPEAT"),
   new Tone(ToneGenerator.TONE_CDMA_HIGH_SS,
     "TONE_CDMA_HIGH_SS",
     "CDMA HIGH SS tone: {3700Hz 25ms, 4000Hz 25ms} repeat 16 times, 400ms OFF, repeat ...."),
   new Tone(ToneGenerator.TONE_CDMA_HIGH_SSL,
     "TONE_CDMA_HIGH_SSL",
     "CDMA HIGH SSL tone: {3700Hz 25ms, 4000Hz 25ms} 8 times, 200ms OFF, {3700Hz 25ms, 4000Hz 25ms} repeat 8 times, 200ms OFF, {3700Hz 25ms, 4000Hz 25ms} repeat 16 times, 4000ms OFF, repeat ..."),
   new Tone(ToneGenerator.TONE_CDMA_HIGH_SS_2,
     "TONE_CDMA_HIGH_SS_2",
     "CDMA HIGH SS2 tone: {3700Hz 25ms, 4000Hz 25ms} 20 times, 1000ms OFF, {3700Hz 25ms, 4000Hz 25ms} 20 times, 3000ms OFF, repeat ...."),
   new Tone(ToneGenerator.TONE_CDMA_HIGH_S_X4,
     "TONE_CDMA_HIGH_S_X4",
     "CDMA HIGH S X4 tone: {3700Hz 25ms, 4000Hz 25ms} 10 times, 500ms OFF, {3700Hz 25ms, 4000Hz 25ms} 10 times, 500ms OFF, {3700Hz 25ms, 4000Hz 25ms} 10 times, 500ms OFF, {3700Hz 25ms, 4000Hz 25ms} 10 times, 2500ms OFF, REPEAT...."),
   new Tone(ToneGenerator.TONE_CDMA_INTERCEPT,
     "TONE_CDMA_INTERCEPT",
     "CDMA Intercept tone: 440Hz 250ms ON, 620Hz 250ms ON ..."),
   new Tone(ToneGenerator.TONE_CDMA_KEYPAD_VOLUME_KEY_LITE,
     "TONE_CDMA_KEYPAD_VOLUME_KEY_LITE", 
     "CDMA KEYPAD Volume key lite tone: 941Hz+1477Hz 120ms ON"),
   new Tone(ToneGenerator.TONE_CDMA_LOW_L,
     "TONE_CDMA_LOW_L", 
     "TONE_CDMA_LOW_L tone: {1300Hz 25ms, 1450Hz 25ms} 40 times, 4000ms OFF, Repeat ...."),
   new Tone(ToneGenerator.TONE_CDMA_LOW_PBX_L,
     "TONE_CDMA_LOW_PBX_L",
     "CDMA LOW PBX L: {1300Hz 25ms,1450Hz 25ms}20 times, 2000ms OFF, REPEAT...."),
   new Tone(ToneGenerator.TONE_CDMA_LOW_PBX_SLS,
     "TONE_CDMA_LOW_PBX_SLS",
     "CDMA HIGH PBX SLS tone:{1300Hz 25ms, 1450Hz 25ms} 8 times 200ms OFF, {1300Hz 25ms, 1450Hz 25ms} 16 times, 200ms OFF, {1300Hz 25ms, 1450Hz 25ms} 8 times, 1000ms OFF, REPEAT...."),
   new Tone(ToneGenerator.TONE_CDMA_LOW_PBX_SS,
     "TONE_CDMA_LOW_PBX_SS",
     "CDMA LOW PBX SS tone: {1300Hz 25ms, 1450Hz 25ms} 8 times 200 ms OFF, {1300Hz 25ms 1450Hz 25ms}8 times, 2000ms OFF, REPEAT...."),
   new Tone(ToneGenerator.TONE_CDMA_LOW_PBX_SSL,
     "TONE_CDMA_LOW_PBX_SSL",
     "CDMA LOW PBX SSL tone:{1300Hz 25ms, 1450Hz 25ms} 8 times 200ms OFF, {1300Hz 25ms, 1450Hz 25ms} 8 times, 200ms OFF, {1300Hz 25ms, 1450Hz 25ms} 16 times, 1000ms OFF, REPEAT...."),
   new Tone(ToneGenerator.TONE_CDMA_LOW_PBX_S_X4,
     "TONE_CDMA_LOW_PBX_S_X4",
     "CDMA LOW PBX X S4 tone: {1300Hz 25ms 1450Hz 25ms} 8 times, 200ms OFF, {1300Hz 25ms 1450Hz 25ms} 8 times, 200ms OFF, {1300Hz 25ms 1450Hz 25ms} 8 times, 200ms OFF, {1300Hz 25ms 1450Hz 25ms} 8 times, 800ms OFF, REPEAT..."),
   new Tone(ToneGenerator.TONE_CDMA_LOW_SLS,
     "TONE_CDMA_LOW_SLS",
     "CDMA LOW SLS tone: {1300Hz 25ms, 1450Hz 25ms} 10 times, 500ms OFF, {1300Hz 25ms, 1450Hz 25ms} 20 times, 500ms OFF, {1300Hz 25ms, 1450Hz 25ms} 10 times, 3000ms OFF, REPEAT"),
   new Tone(ToneGenerator.TONE_CDMA_LOW_SS,
     "TONE_CDMA_LOW_SS",
     "CDMA LOW SS tone: {1300z 25ms, 1450Hz 25ms} repeat 16 times, 400ms OFF, repeat ...."),
   new Tone(ToneGenerator.TONE_CDMA_LOW_SSL,
     "TONE_CDMA_LOW_SSL",
     "CDMA LOW SSL tone: {1300Hz 25ms, 1450Hz 25ms} 8 times, 200ms OFF, {1300Hz 25ms, 1450Hz 25ms} repeat 8 times, 200ms OFF, {1300Hz 25ms, 1450Hz 25ms} repeat 16 times, 4000ms OFF, repeat ..."),
   new Tone(ToneGenerator.TONE_CDMA_LOW_SS_2,
     "TONE_CDMA_LOW_SS_2",
     "CDMA LOW SS2 tone: {1300Hz 25ms, 1450Hz 25ms} 20 times, 1000ms OFF, {1300Hz 25ms, 1450Hz 25ms} 20 times, 3000ms OFF, repeat ...."),
   new Tone(ToneGenerator.TONE_CDMA_LOW_S_X4,
     "TONE_CDMA_LOW_S_X4",
     "CDMA LOW S X4 tone: {2600Hz 25ms, 2900Hz 25ms} 10 times, 500ms OFF, {2600Hz 25ms, 2900Hz 25ms} 10 times, 500ms OFF, {2600Hz 25ms, 2900Hz 25ms} 10 times, 500ms OFF, {2600Hz 25ms, 2900Hz 25ms} 10 times, 2500ms OFF, REPEAT...."),
   new Tone(ToneGenerator.TONE_CDMA_MED_L,
     "TONE_CDMA_MED_L",
     "TONE_CDMA_MED_L tone: {2600Hz 25ms, 2900Hz 25ms} 40 times 4000ms OFF, Repeat ...."),
   new Tone(ToneGenerator.TONE_CDMA_MED_PBX_L,
     "TONE_CDMA_MED_PBX_L",
     "CDMA MED PBX L: {2600Hz 25ms, 2900Hz 25ms}20 times, 2000ms OFF, REPEAT...."),
   new Tone(ToneGenerator.TONE_CDMA_MED_PBX_SLS,
     "TONE_CDMA_MED_PBX_SLS",
     "CDMA HIGH PBX SLS tone:{2600Hz 25ms, 2900Hz 25ms} 8 times 200ms OFF, {2600Hz 25ms, 2900Hz 25ms} 16 times, 200ms OFF, {2600Hz 25ms, 2900Hz 25ms} 8 times, 1000ms OFF, REPEAT...."),
   new Tone(ToneGenerator.TONE_CDMA_MED_PBX_SS,
     "TONE_CDMA_MED_PBX_SS",
     "CDMA MED PBX SS tone: {2600Hz 25ms, 2900Hz 25ms} 8 times 200 ms OFF, {2600Hz 25ms 2900Hz 25ms}8 times, 2000ms OFF, REPEAT...."),
   new Tone(ToneGenerator.TONE_CDMA_MED_PBX_SSL,
     "TONE_CDMA_MED_PBX_SSL",
     "CDMA MED PBX SSL tone:{2600Hz 25ms, 2900Hz 25ms} 8 times 200ms OFF, {2600Hz 25ms, 2900Hz 25ms} 8 times, 200ms OFF, {2600Hz 25ms, 2900Hz 25ms} 16 times, 1000ms OFF, REPEAT...."),
   new Tone(ToneGenerator.TONE_CDMA_MED_PBX_S_X4,
     "TONE_CDMA_MED_PBX_S_X4",
     "CDMA MED PBX X S4 tone: {2600Hz 25ms 2900Hz 25ms} 8 times, 200ms OFF, {2600Hz 25ms 2900Hz 25ms} 8 times, 200ms OFF, {2600Hz 25ms 2900Hz 25ms} 8 times, 200ms OFF, {2600Hz 25ms 2900Hz 25ms} 8 times, 800ms OFF, REPEAT..."),
   new Tone(ToneGenerator.TONE_CDMA_MED_SLS,
     "TONE_CDMA_MED_SLS",
     "CDMA MED SLS tone: {2600Hz 25ms, 2900Hz 25ms} 10 times, 500ms OFF, {2600Hz 25ms, 2900Hz 25ms} 20 times, 500ms OFF, {2600Hz 25ms, 2900Hz 25ms} 10 times, 3000ms OFF, REPEAT"),
   new Tone(ToneGenerator.TONE_CDMA_MED_SS,
     "TONE_CDMA_MED_SS",
     "CDMA MED SS tone: {2600Hz 25ms, 2900Hz 25ms} repeat 16 times, 400ms OFF, repeat ...."),
   new Tone(ToneGenerator.TONE_CDMA_MED_SSL,
     "TONE_CDMA_MED_SSL",
     "CDMA MED SSL tone: {2600Hz 25ms, 2900Hz 25ms} 8 times, 200ms OFF, {2600Hz 25ms, 2900Hz 25ms} repeat 8 times, 200ms OFF, {2600Hz 25ms, 2900Hz 25ms} repeat 16 times, 4000ms OFF, repeat ..."),
   new Tone(ToneGenerator.TONE_CDMA_MED_SS_2,
     "TONE_CDMA_MED_SS_2",
     "CDMA MED SS2 tone: {2600Hz 25ms, 2900Hz 25ms} 20 times, 1000ms OFF, {2600Hz 25ms, 2900Hz 25ms} 20 times, 3000ms OFF, repeat ...."),
   new Tone(ToneGenerator.TONE_CDMA_MED_S_X4,
     "TONE_CDMA_MED_S_X4",
     "CDMA MED S X4 tone: {2600Hz 25ms, 2900Hz 25ms} 10 times, 500ms OFF, {2600Hz 25ms, 2900Hz 25ms} 10 times, 500ms OFF, {2600Hz 25ms, 2900Hz 25ms} 10 times, 500ms OFF, {2600Hz 25ms, 2900Hz 25ms} 10 times, 2500ms OFF, REPEAT...."),
   new Tone(ToneGenerator.TONE_CDMA_NETWORK_BUSY,
     "TONE_CDMA_NETWORK_BUSY",
     "CDMA Network Busy tone: 480Hz+620Hz 500ms ON, 500ms OFF continuous"),
   new Tone(ToneGenerator.TONE_CDMA_NETWORK_BUSY_ONE_SHOT,
     "TONE_CDMA_NETWORK_BUSY_ONE_SHOT",
     "CDMA_NETWORK_BUSY_ONE_SHOT tone: 425Hz 500ms ON, 500ms OFF."),
   new Tone(ToneGenerator.TONE_CDMA_NETWORK_CALLWAITING,
     "TONE_CDMA_NETWORK_CALLWAITING",
     "CDMA Network Callwaiting tone: 440Hz 300ms ON"),
   new Tone(ToneGenerator.TONE_CDMA_NETWORK_USA_RINGBACK,
     "TONE_CDMA_NETWORK_USA_RINGBACK",
     "CDMA USA Ringback: 440Hz+480Hz 2s ON, 4000 OFF ..."),
   new Tone(ToneGenerator.TONE_CDMA_ONE_MIN_BEEP,
     "TONE_CDMA_ONE_MIN_BEEP",
     "CDMA One Min Beep tone: 1150Hz+770Hz 400ms ON"),
   new Tone(ToneGenerator.TONE_CDMA_PIP,
     "TONE_CDMA_PIP",
     "CDMA PIP tone: 480Hz 100ms ON, 100ms OFF repeated for 4 times"),
   new Tone(ToneGenerator.TONE_CDMA_PRESSHOLDKEY_LITE,
     "TONE_CDMA_PRESSHOLDKEY_LITE",
     "CDMA PRESSHOLDKEY LITE tone: 587Hz 375ms ON, 1175Hz 125ms ON"),
   new Tone(ToneGenerator.TONE_CDMA_REORDER,
     "TONE_CDMA_REORDER",
     "CDMA Reorder tone: 480Hz+620Hz 250ms ON, 250ms OFF..."),
   new Tone(ToneGenerator.TONE_CDMA_SIGNAL_OFF,
     "TONE_CDMA_SIGNAL_OFF",
     "CDMA_SIGNAL_OFF - silent tone"),
   new Tone(ToneGenerator.TONE_CDMA_SOFT_ERROR_LITE,
     "TONE_CDMA_SOFT_ERROR_LITE",
     "CDMA SOFT ERROR LITE tone: 1047Hz 125ms ON, 370Hz 125ms"),
   new Tone(ToneGenerator.TONE_DTMF_0,
     "TONE_DTMF_0",
     "DTMF tone for key 0: 1336Hz, 941Hz, continuous"),
   new Tone(ToneGenerator.TONE_DTMF_1,
     "TONE_DTMF_1",
     "DTMF tone for key 1: 1209Hz, 697Hz, continuous"),
   new Tone(ToneGenerator.TONE_DTMF_2,
     "TONE_DTMF_2",
     "DTMF tone for key 2: 1336Hz, 697Hz, continuous"),
   new Tone(ToneGenerator.TONE_DTMF_3,
     "TONE_DTMF_3",
     "DTMF tone for key 3: 1477Hz, 697Hz, continuous"),
   new Tone(ToneGenerator.TONE_DTMF_4,
     "TONE_DTMF_4",
     "DTMF tone for key 4: 1209Hz, 770Hz, continuous"),
   new Tone(ToneGenerator.TONE_DTMF_5,
     "TONE_DTMF_5",
     "DTMF tone for key 5: 1336Hz, 770Hz, continuous"),
   new Tone(ToneGenerator.TONE_DTMF_6,
     "TONE_DTMF_6",
     "DTMF tone for key 6: 1477Hz, 770Hz, continuous"),
   new Tone(ToneGenerator.TONE_DTMF_7,
     "TONE_DTMF_7",
     "DTMF tone for key 7: 1209Hz, 852Hz, continuous"),
   new Tone(ToneGenerator.TONE_DTMF_8,
     "TONE_DTMF_8",
     "DTMF tone for key 8: 1336Hz, 852Hz, continuous"),
   new Tone(ToneGenerator.TONE_DTMF_9,
     "TONE_DTMF_9",
     "DTMF tone for key 9: 1477Hz, 852Hz, continuous"),
   new Tone(ToneGenerator.TONE_DTMF_A,
     "TONE_DTMF_A",
     "DTMF tone for key A: 1633Hz, 697Hz, continuous"),
   new Tone(ToneGenerator.TONE_DTMF_B,
     "TONE_DTMF_B",
     "DTMF tone for key B: 1633Hz, 770Hz, continuous"),
   new Tone(ToneGenerator.TONE_DTMF_C,
     "TONE_DTMF_C",
     "DTMF tone for key C: 1633Hz, 852Hz, continuous"),
   new Tone(ToneGenerator.TONE_DTMF_D,
     "TONE_DTMF_D",
     "DTMF tone for key D: 1633Hz, 941Hz, continuous"),
   new Tone(ToneGenerator.TONE_DTMF_P,
     "TONE_DTMF_P",
     "DTMF tone for key #: 1477Hz, 941Hz, continuous"),
   new Tone(ToneGenerator.TONE_DTMF_S,
     "TONE_DTMF_S",
     "DTMF tone for key *: 1209Hz, 941Hz, continuous"),
   new Tone(ToneGenerator.TONE_PROP_ACK,
     "TONE_PROP_ACK",
     "Proprietary tone, positive acknowlegement: 1200Hz, 100ms ON, 100ms OFF 2 bursts"),
   new Tone(ToneGenerator.TONE_PROP_BEEP,
     "TONE_PROP_BEEP",
     "Proprietary tone, general beep: 400Hz+1200Hz, 35ms ON"),
   new Tone(ToneGenerator.TONE_PROP_BEEP2,
     "TONE_PROP_BEEP2",
     "Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON"),
   new Tone(ToneGenerator.TONE_PROP_NACK,
     "TONE_PROP_NACK",
     "Proprietary tone, negative acknowlegement: 300Hz+400Hz+500Hz, 400ms ON"),
   new Tone(ToneGenerator.TONE_PROP_PROMPT,
     "TONE_PROP_PROMPT",
     "Proprietary tone, prompt tone: 400Hz+1200Hz, 200ms ON"),
   new Tone(ToneGenerator.TONE_SUP_BUSY,
     "TONE_SUP_BUSY",
     "Call supervisory tone, Busy: CEPT: 425Hz, 500ms ON, 500ms OFF..."),
   new Tone(ToneGenerator.TONE_SUP_CALL_WAITING,
     "TONE_SUP_CALL_WAITING",
     "Call supervisory tone, Call Waiting: CEPT, JAPAN: 425Hz, 200ms ON, 600ms OFF, 200ms ON, 3s OFF..."),
   new Tone(ToneGenerator.TONE_SUP_CONFIRM,
     "TONE_SUP_CONFIRM",
     "Call supervisory tone (IS-95), confirm tone: a 350 Hz tone added to a 440 Hz tone repeated 3 times in a 100 ms on, 100 ms off cycle"),
   new Tone(ToneGenerator.TONE_SUP_CONGESTION,
     "TONE_SUP_CONGESTION",
     "Call supervisory tone, Congestion: CEPT, JAPAN: 425Hz, 200ms ON, 200ms OFF..."),
   new Tone(ToneGenerator.TONE_SUP_CONGESTION_ABBREV,
     "TONE_SUP_CONGESTION_ABBREV",
     "Call supervisory tone (IS-95), abbreviated congestion: congestion tone limited to 4 seconds"),
   new Tone(ToneGenerator.TONE_SUP_DIAL,
     "TONE_SUP_DIAL",
     "Call supervisory tone, Dial tone: CEPT: 425Hz, continuous ANSI (IS-95): 350Hz+440Hz, continuous JAPAN: 400Hz, continuous"),
   new Tone(ToneGenerator.TONE_SUP_ERROR,
     "TONE_SUP_ERROR",
     "Call supervisory tone, Error/Special info: 950Hz+1400Hz+1800Hz, 330ms ON, 1s OFF..."),
   new Tone(ToneGenerator.TONE_SUP_INTERCEPT,
     "TONE_SUP_INTERCEPT",
     "Call supervisory tone (IS-95), intercept tone: alternating 440 Hz and 620 Hz tones, each on for 250 ms"),
   new Tone(ToneGenerator.TONE_SUP_INTERCEPT_ABBREV,
     "TONE_SUP_INTERCEPT_ABBREV",
     "Call supervisory tone (IS-95), abbreviated intercept: intercept tone limited to 4 seconds"),
   new Tone(ToneGenerator.TONE_SUP_PIP,
     "TONE_SUP_PIP",
     "Call supervisory tone (IS-95), pip tone: four bursts of 480 Hz tone (0.1 s on, 0.1 s off)."),
   new Tone(ToneGenerator.TONE_SUP_RADIO_ACK,
     "TONE_SUP_RADIO_ACK",
     "Call supervisory tone, Radio path acknowlegment : CEPT, ANSI: 425Hz, 200ms ON JAPAN: 400Hz, 1s ON, 2s OFF..."),
   new Tone(ToneGenerator.TONE_SUP_RADIO_NOTAVAIL,
     "TONE_SUP_RADIO_NOTAVAIL",
     "Call supervisory tone, Radio path not available: 425Hz, 200ms ON, 200 OFF 3 bursts"),
   new Tone(ToneGenerator.TONE_SUP_RINGTONE,
     "TONE_SUP_RINGTONE",
     "Call supervisory tone, Ring Tone: CEPT, JAPAN: 425Hz, 1s ON, 4s OFF...")
 };
 
 SeekBar toneDurBar;
 TextView toneDurText;
 
 ListView toneList;
 public ToneArrayAdapter toneListAdapter;

 ToneGenerator toneGenerator;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        toneGenerator = new ToneGenerator(AudioManager.STREAM_MUSIC, 100);
        
        toneDurBar = (SeekBar)findViewById(R.id.tonedur);
        toneDurText = (TextView)findViewById(R.id.tonedurtext);
        toneDurText.setText(toneDurBar.getProgress() + " ms");
        toneDurBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener(){

   @Override
   public void onProgressChanged(SeekBar seekBar, int progress,
     boolean fromUser) {
    toneDurText.setText(progress + " ms");
   }

   @Override
   public void onStartTrackingTouch(SeekBar seekBar) {
    // TODO Auto-generated method stub
    
   }

   @Override
   public void onStopTrackingTouch(SeekBar seekBar) {
    // TODO Auto-generated method stub
    
   }});
        
        toneList = (ListView)findViewById(R.id.tonelist);
        toneListAdapter = new ToneArrayAdapter(this,
                R.layout.row, tones);
        
        toneList.setAdapter(toneListAdapter);
        
        toneList.setOnItemClickListener(new OnItemClickListener(){

   @Override
   public void onItemClick(AdapterView<?> parent, View view,
     int position, long id) {
    Tone t = (Tone)parent.getItemAtPosition(position);
    int type = t.toneType;
    int durationMs = toneDurBar.getProgress();
    toneGenerator.startTone(type, durationMs);
    
   }});

    }

}

/res/layout/activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context="com.example.androidtonegenerator.MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />
    
    <SeekBar
        android:id="@+id/tonedur"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="5000"
        android:progress="1000"/>
    
    <TextView
        android:id="@+id/tonedurtext"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="right"/>
    
    <ListView 
        android:id="@+id/tonelist"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

/res/layout/row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/name"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textStyle="bold"
        android:textSize="22px" />

    <TextView
        android:id="@+id/desc"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textStyle="italic"
        android:textSize="18px" />

</LinearLayout>


download filesDownload the files.

Download APK.

Wednesday, December 3, 2014

DTMF Piano using ToneGenerator

Example to generate DTMF tones using ToneGenerator.


MainActivity.java
package com.example.androiddtmfpiano;

import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.GridView;
import android.media.AudioManager;
import android.media.ToneGenerator;
import android.os.Bundle;

public class MainActivity extends ActionBarActivity {
 
 GridView gridView;
  
 static final String[] numbers = new String[] { 
   "1", "2", "3",
   "4", "5", "6",
   "7", "8", "9",
   "*", "0", "#"};
 
 static final int[] toneTypes = new int[]{
  ToneGenerator.TONE_DTMF_1,
  ToneGenerator.TONE_DTMF_2,
  ToneGenerator.TONE_DTMF_3,
  ToneGenerator.TONE_DTMF_4,
  ToneGenerator.TONE_DTMF_5,
  ToneGenerator.TONE_DTMF_6,
  ToneGenerator.TONE_DTMF_7,
  ToneGenerator.TONE_DTMF_8,
  ToneGenerator.TONE_DTMF_9,
  ToneGenerator.TONE_DTMF_S, //*
  ToneGenerator.TONE_DTMF_0,
  ToneGenerator.TONE_DTMF_P //#
 };
 
 static int streamType = AudioManager.STREAM_MUSIC;
    static int volume = 50;
    static int durationMs = 100;
 static final ToneGenerator toneGenerator = 
   new ToneGenerator(streamType, volume);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        gridView = (GridView) findViewById(R.id.gridView);
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(
         this, android.R.layout.simple_list_item_1, numbers);
        
        gridView.setAdapter(adapter);
        
        gridView.setOnItemClickListener(new OnItemClickListener() {

   @Override
   public void onItemClick(AdapterView<?> parent, View view,
     int position, long id) {
       toneGenerator.startTone(toneTypes[position], durationMs);
   }});
    }

}

activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.androiddtmfpiano.MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />

    <GridView
        android:id="@+id/gridView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:columnWidth="50dp"
        android:gravity="center"
        android:numColumns="3"
        android:stretchMode="columnWidth" >
    </GridView>

</LinearLayout>

Next example:
Visible DTMF Piano: Visualizer + ToneGenerator

Tuesday, December 2, 2014

android.media.ToneGenerator simple example

android.media.ToneGenerator provides methods to play DTMF tones (ITU-T Recommendation Q.23), call supervisory tones (3GPP TS 22.001, CEPT) and proprietary tones (3GPP TS 31.111). Depending on call state and routing options, tones are mixed to the downlink audio or output to the speaker phone or headset. This API is not for generating tones over the uplink audio path.


MainActivity.java
package com.example.androidtonegenerator;

import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ToggleButton;
import android.media.AudioManager;
import android.media.ToneGenerator;
import android.os.Bundle;


public class MainActivity extends ActionBarActivity {
 
 Button btnGenTone0;
 ToggleButton tgbtnGenTone1;
 
 ToneGenerator toneGenerator1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btnGenTone0 = (Button)findViewById(R.id.gentone0);
        tgbtnGenTone1 = (ToggleButton)findViewById(R.id.gentone1);
        
        btnGenTone0.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View v) {
    int streamType = AudioManager.STREAM_MUSIC;
    int volume = 50;
    ToneGenerator toneGenerator = new ToneGenerator(streamType, volume);
    int toneType = ToneGenerator.TONE_DTMF_0;
    int durationMs = 500;
    toneGenerator.startTone(toneType, durationMs);
   }});
        
        toneGenerator1 = new ToneGenerator(AudioManager.STREAM_MUSIC, 50);
        
        tgbtnGenTone1.setOnCheckedChangeListener(new OnCheckedChangeListener(){

   @Override
   public void onCheckedChanged(CompoundButton buttonView,
     boolean isChecked) {
    if(isChecked){
     toneGenerator1.startTone(ToneGenerator.TONE_DTMF_1);
    }else{
     toneGenerator1.stopTone();
    }
   }});
    }

}

activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context="com.example.androidtonegenerator.MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />

    <Button
        android:id="@+id/gentone0"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Generate Tone: TONE_DTMF_0" />
    
    <ToggleButton
        android:id="@+id/gentone1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textOn="Stop Tone: TONE_DTMF_1"
        android:textOff="Start Tone: TONE_DTMF_1" />
</LinearLayout>

Next:
- DTMF Piano using ToneGenerator
Sound samples generated by android.media.ToneGenerator