Skip to content

Commit

Permalink
Added lots of visualizer code.
Browse files Browse the repository at this point in the history
  • Loading branch information
matthew-compton committed Jul 28, 2014
1 parent f410a2d commit 52a817e
Show file tree
Hide file tree
Showing 14 changed files with 269 additions and 86 deletions.
3 changes: 3 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ambergleam.visualizer">

<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
Expand Down
62 changes: 62 additions & 0 deletions app/src/main/java/com/ambergleam/visualizer/AudioPlayer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.ambergleam.visualizer;

import android.content.Context;
import android.media.MediaPlayer;

public class AudioPlayer extends MediaPlayer {

private MediaPlayer mPlayer;

public enum STATE {
PLAYING,
PAUSED,
STOPPED
}

private int mLength;
private STATE mState;

public AudioPlayer() {
mState = STATE.STOPPED;
}

public void play(Context c, int id) {
stop();

mState = STATE.PLAYING;
mPlayer = MediaPlayer.create(c, id);
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
stop();
}
});

mPlayer.start();
}

public void pause() {
mState = STATE.PAUSED;
mPlayer.pause();
mLength = mPlayer.getCurrentPosition();
}

public void stop() {
mState = STATE.STOPPED;
if (mPlayer != null) {
mPlayer.release();
mPlayer = null;
}
}

public void resume() {
mState = STATE.PLAYING;
mPlayer.seekTo(mLength);
mPlayer.start();
}

public STATE getState() {
return mState;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ protected void onCreate(Bundle savedInstanceState) {
}
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ protected Fragment createFragment() {
return new VisualizerFragment();
}

}
}
109 changes: 81 additions & 28 deletions app/src/main/java/com/ambergleam/visualizer/VisualizerFragment.java
Original file line number Diff line number Diff line change
@@ -1,60 +1,113 @@
package com.ambergleam.visualizer;

import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.annotation.TargetApi;
import android.os.Build;
import android.media.AudioManager;
import android.media.audiofx.Visualizer;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.widget.ImageButton;
import android.widget.LinearLayout;

import java.util.Random;
import com.ambergleam.visualizer.AudioPlayer.STATE;

public class VisualizerFragment extends Fragment {

private static Random sRandom = new Random();
private AnimatorSet mAnimatorSet;
private static final float VISUALIZER_HEIGHT_DIP = 50f;

private View mOrbView;
private int orb_x;
private int orb_y;
private AudioPlayer mAudioPlayer;
private Visualizer mVisualizer;

private LinearLayout mFrame;
private VisualizerView mVisualizerView;
private ImageButton mPlayButton;
private ImageButton mPauseButton;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_sunset, container, false);
View view = inflater.inflate(R.layout.fragment_visualizer, container, false);

mOrbView = view.findViewById(R.id.orb);
getActivity().setVolumeControlStream(AudioManager.STREAM_MUSIC);
mAudioPlayer = new AudioPlayer();

view.setOnClickListener(new View.OnClickListener() {
@TargetApi(Build.VERSION_CODES.KITKAT)
mPlayButton = (ImageButton) view.findViewById(R.id.play);
mPlayButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startVisualizer();
if (mAudioPlayer.getState() == STATE.PAUSED) {
mAudioPlayer.resume();
} else {
mAudioPlayer.play(getActivity(), R.raw.test_audio);
mVisualizer = new Visualizer(mAudioPlayer.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);
}
updateUI();
}
});

orb_x = view.getWidth() / 2;
orb_y = view.getHeight() / 2;
mPauseButton = (ImageButton) view.findViewById(R.id.pause);
mPauseButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mAudioPlayer.pause();
updateUI();
}
});

mOrbView.setX(orb_x);
mOrbView.setX(orb_y);
mFrame = (LinearLayout) view.findViewById(R.id.frame);
mVisualizerView = new VisualizerView(getActivity());
mVisualizerView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (int) (VISUALIZER_HEIGHT_DIP * getResources().getDisplayMetrics().density)));
mFrame.addView(mVisualizerView);

return view;
}

private void startVisualizer() {
ObjectAnimator orbAnimatorX = ObjectAnimator.ofFloat(mOrbView, "x", orb_x, orb_x + sRandom.nextInt(400)).setDuration(1000);
orbAnimatorX.setInterpolator(new AccelerateInterpolator());
@Override
public void onResume() {
super.onResume();
updateUI();
}

ObjectAnimator orbAnimatorY = ObjectAnimator.ofFloat(mOrbView, "y", orb_y, orb_y + sRandom.nextInt(400)).setDuration(1000);
orbAnimatorY.setInterpolator(new AccelerateInterpolator());
@Override
public void onPause() {
super.onPause();
if (mVisualizer != null) {
mVisualizer.release();
}
mAudioPlayer.stop();
}

mAnimatorSet = new AnimatorSet();
mAnimatorSet.play(orbAnimatorX).with(orbAnimatorY);
mAnimatorSet.start();
private void updateUI() {
switch (mAudioPlayer.getState()) {
case PAUSED:
case STOPPED:
if (mVisualizer != null) {
mVisualizerView.setEnabled(false);
}
mPauseButton.setEnabled(false);
mPlayButton.setEnabled(true);
break;
case PLAYING:
if (mVisualizer != null) {
mVisualizerView.setEnabled(true);
}
mPauseButton.setEnabled(true);
mPlayButton.setEnabled(false);
break;
default:
break;
}
}

}
77 changes: 77 additions & 0 deletions app/src/main/java/com/ambergleam/visualizer/VisualizerView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package com.ambergleam.visualizer;

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;

/**
* A simple class that draws waveform data received from a
* {@link android.media.audiofx.Visualizer.OnDataCaptureListener#onWaveFormDataCapture }
*/
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 defStyle) {
super(context, attrs, defStyle);
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);
}

}
14 changes: 0 additions & 14 deletions app/src/main/res/drawable/orb.xml

This file was deleted.

11 changes: 6 additions & 5 deletions app/src/main/res/layout/activity_fragment.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/fragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent" >
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/fragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent">

</FrameLayout>
</FrameLayout>
18 changes: 0 additions & 18 deletions app/src/main/res/layout/fragment_sunset.xml

This file was deleted.

32 changes: 32 additions & 0 deletions app/src/main/res/layout/fragment_visualizer.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/frame"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="@dimen/activity_horizontal_margin">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center|bottom">

<ImageButton
android:id="@+id/play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:src="@android:drawable/ic_media_play"
/>

<ImageButton
android:id="@+id/pause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:src="@android:drawable/ic_media_pause"
/>

</LinearLayout>

</LinearLayout>
Loading

0 comments on commit 52a817e

Please sign in to comment.