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:

swapnil_gt said...

Works perfectly. Thanks !!

vabym said...

Perfect !!!

Unknown 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);

}

Unknown 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

Anonymous said...

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

Unknown 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)

Unknown 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!

Erik said...

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

Unknown said...

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

Just add the following to your app manifest xml:

Unknown said...

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

Anonymous said...

Thanks for the post works like a charm

Unknown said...

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?

Erik said...

hello Alien LB,

You can remove it.

Unknown said...

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..

Unknown said...

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.

paridhi said...

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.

Unknown said...

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