Monday, February 9, 2015

Create audio Visualizer for MediaPlayer

This example create audio Visualizer for MediaPlayer, reference Android demo example: ApiDemos > Media > AudioTx. Permission android.permission.RECORD_AUDIO is needed,  to use visualizer.

remark@2016-10-18:
I found that the example code removed from Android Studio examples list, may be it is  NOT work now.



Create custom VisualizerView extends View, VisualizerView.java
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);
 }

}

Add <com.example.androidaudiovisualizer.VisualizerView> to layout file, 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="match_parent" />

</LinearLayout>

MainActivity.java
package com.example.androidaudiovisualizer;

import android.support.v7.app.ActionBarActivity;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.audiofx.Visualizer;
import android.os.Bundle;

/*
 * Copy test.mp3 to /res/raw/ folder
 * 
 * needed in AndroidManifest.xml
 * android:minSdkVersion="9"
 * uses-permission of "android.permission.RECORD_AUDIO"
 * 
 * reference: Android demo example -
 * ApiDemos > Media > AudioTx
 */

public class MainActivity extends ActionBarActivity {

 VisualizerView mVisualizerView;

 private MediaPlayer mMediaPlayer;
 private Visualizer mVisualizer;

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

  initAudio();
 }

 @Override
 protected void onPause() {
  super.onPause();
  if (isFinishing() && mMediaPlayer != null) {
   mVisualizer.release();
   mMediaPlayer.release();
   mMediaPlayer = null;
  }
 }

 private void initAudio() {
  setVolumeControlStream(AudioManager.STREAM_MUSIC);
  mMediaPlayer = MediaPlayer.create(this, R.raw.test);

  setupVisualizerFxAndUI();
  // Make sure the visualizer is enabled only when you actually want to
  // receive data, and
  // when it makes sense to receive data.
  mVisualizer.setEnabled(true);
  // When the stream ends, we don't need to collect any more data. We
  // don't do this in
  // setupVisualizerFxAndUI because we likely want to have more,
  // non-Visualizer related code
  // in this callback.
  mMediaPlayer
    .setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
     public void onCompletion(MediaPlayer mediaPlayer) {
      mVisualizer.setEnabled(false);
     }
    });
  mMediaPlayer.start();

 }

 private void setupVisualizerFxAndUI() {

  // Create the Visualizer object and attach it to our media player.
  mVisualizer = new Visualizer(mMediaPlayer.getAudioSessionId());
  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);
 }

}


Next example:
Visible DTMF Piano: Visualizer + ToneGenerator

13 comments:

swapnil_gt said...

Works perfectly. Thanks !!

vabym said...

Perfect !!!

Mohammd Hadipour said...

Please show me how to use this on voice recorder (Android MediaRecorder) while I'm recording voice.

Sajjad Ak said...

Thank you for Share it.
Thank you very much.

Anonymous said...

Works fine!

In Android 6.0 I had to ask for this permissions in the code to start working

if( ContextCompat.checkSelfPermission(this, Manifest.permission.MODIFY_AUDIO_SETTINGS) == PackageManager.PERMISSION_GRANTED){

}else{
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.MODIFY_AUDIO_SETTINGS},
MY_PERMISSIONS_REQUEST_MODIFY_AUDIO_SETTINGS);

}

if( ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED){

}else{
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.RECORD_AUDIO},
MY_PERMISSIONS_REQUEST_RECORD_AUDIO);

}

Pavel Marian said...

Can you create a vertical bar style for this ?

Behind that, great tutorial and example +1

Sumit Naharia said...

Error code -1 when initializing Visualizer

Yogendra Singh said...

Please show me how to use this on voice recorder (Android MediaRecorder) while I'm recording voice.

ardi nada said...

Thanks before, because it's works perfectly!!
but it's just for one audio, how can make it work for more audio??

anddev said...

Hi~! This a great tutorial and working. Can this be possible for a bar graph?

@ardi nada on MediaPlayer setOnCompletionListener call mVisualizer.setEnabled(false)

ardi nada said...

@anddev thx !! it's work!!
but now i get new question, why when i use this visualizer, i cant use audio effect like BassBoost??

Unknown said...

I'm on android 6.0, when I try to run the app it just tells me 'Unfortunately, audioVisualizer has closed". I gave it the mic permission in my settings. The only thing that I think maybe went wrong with inputting the code was the part at the very top that says something about reference Android demo example: ApiDemos > Media > AudioTx. I don't know what I am supposed to do about that. Any ideas anyone? Thanks!

Andr.oid Eric said...

remark@2016-10-18:
I found that the example code removed from Android Studio examples list, may be it is NOT work now.