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.

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