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

22 comments:

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

    ReplyDelete
  2. Thank you for Share it.
    Thank you very much.

    ReplyDelete
  3. 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);

    }

    ReplyDelete
  4. Can you create a vertical bar style for this ?

    Behind that, great tutorial and example +1

    ReplyDelete
  5. Error code -1 when initializing Visualizer

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

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

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

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

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

    ReplyDelete
  10. 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!

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

    ReplyDelete
  12. Sumit Naharia It's a permission problem, see here: http://stackoverflow.com/a/28427213

    Just add the following to your app manifest xml:

    ReplyDelete
  13. Hi! I get this error on Android 6.0 (LG Spirit):
    Cannot initialize Visualizer engine, error: -3

    ReplyDelete
  14. Thanks for the post works like a charm

    ReplyDelete
  15. 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" >

    what is this? These things keep ocurring errors.... what to do?

    ReplyDelete
  16. hello Alien LB,

    You can remove it.

    ReplyDelete
  17. Still its not working...

    android.view.InflateException: Binary XML file line #20: Binary XML file line #20: Error inflating class com.example.androidaudiovisualizer.VisualizerView

    i am getting this kind of error..
    please can anyone help me..

    ReplyDelete
  18. I also won't able to run.Please anyone can help.How to connect music with visualizer in order to get effect of high note and low note.

    ReplyDelete
  19. Hey,
    Thanks for an amazing tutorial. Although while running the application I am facing a run time exception. java.lang.RuntimeException: Cannot initialize Visualizer engine, error: -1 .
    After installation, the permission section of the application doesn't have "Audio" related permissions. Please help me with this.

    ReplyDelete
  20. How to apply that in a "vertical-bars" way?

    ReplyDelete