aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelix Palmer <felix.palmer@metaswitch.com>2011-12-02 17:10:51 -0800
committerFelix Palmer <felix.palmer@metaswitch.com>2011-12-02 17:10:51 -0800
commit6fa6928b1e07f0004b05a5aed1634b0e43096054 (patch)
tree773866a303b8ba641bed83984c02b63377b4ffdd
parent348bb37f8e8fcb902c9a2f1dd59fd5c8ee3cae4d (diff)
downloadandroid_external_android-visualizer-6fa6928b1e07f0004b05a5aed1634b0e43096054.tar.gz
android_external_android-visualizer-6fa6928b1e07f0004b05a5aed1634b0e43096054.tar.bz2
android_external_android-visualizer-6fa6928b1e07f0004b05a5aed1634b0e43096054.zip
Recfactor FFT rendering into separate class
-rw-r--r--src/com/pheelicks/visualizer/AudioData.java12
-rw-r--r--src/com/pheelicks/visualizer/BarGraphRenderer.java62
-rw-r--r--src/com/pheelicks/visualizer/FFTData.java12
-rw-r--r--src/com/pheelicks/visualizer/Renderer.java64
-rw-r--r--src/com/pheelicks/visualizer/VisualizerActivity.java31
-rw-r--r--src/com/pheelicks/visualizer/VisualizerView.java66
6 files changed, 198 insertions, 49 deletions
diff --git a/src/com/pheelicks/visualizer/AudioData.java b/src/com/pheelicks/visualizer/AudioData.java
new file mode 100644
index 0000000..9beb004
--- /dev/null
+++ b/src/com/pheelicks/visualizer/AudioData.java
@@ -0,0 +1,12 @@
+package com.pheelicks.visualizer;
+
+// Data class to explicitly indicate that these bytes are raw audio data
+public class AudioData
+{
+ public AudioData(byte[] bytes)
+ {
+ this.bytes = bytes;
+ }
+
+ public byte[] bytes;
+}
diff --git a/src/com/pheelicks/visualizer/BarGraphRenderer.java b/src/com/pheelicks/visualizer/BarGraphRenderer.java
new file mode 100644
index 0000000..f1531e9
--- /dev/null
+++ b/src/com/pheelicks/visualizer/BarGraphRenderer.java
@@ -0,0 +1,62 @@
+package com.pheelicks.visualizer;
+
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+
+public class BarGraphRenderer extends Renderer
+{
+ private int mDivisions;
+ private Paint mPaint;
+ private boolean mTop;
+
+ /**
+ * Renders the FFT data as a series of lines, in histogram form
+ * @param canvas
+ * @param divisions - must be a power of 2. Controls how many lines to draw
+ * @param paint - Paint to draw lines with
+ * @param top - whether to draw the lines at the top of the canvas, or the bottom
+ */
+ public BarGraphRenderer(Canvas canvas,
+ int divisions,
+ Paint paint,
+ boolean top)
+ {
+ super(canvas);
+ mDivisions = divisions;
+ mPaint = paint;
+ mTop = top;
+ }
+
+ @Override
+ public void onRender(AudioData data, Rect rect)
+ {
+ // Do nothing, we only display FFT data
+ }
+
+ @Override
+ public void onRender(FFTData data, Rect rect)
+ {
+ for (int i = 0; i < data.bytes.length / mDivisions; i++) {
+ mFFTPoints[i * 4] = i * 4 * mDivisions;
+ mFFTPoints[i * 4 + 2] = i * 4 * mDivisions;
+ byte rfk = data.bytes[mDivisions * i];
+ byte ifk = data.bytes[mDivisions * i + 1];
+ float magnitude = (rfk * rfk + ifk * ifk);
+ int dbValue = (int) (10 * Math.log10(magnitude));
+
+ if(mTop)
+ {
+ mFFTPoints[i * 4 + 1] = 0;
+ mFFTPoints[i * 4 + 3] = (dbValue * 2 - 10);
+ }
+ else
+ {
+ mFFTPoints[i * 4 + 1] = rect.height();
+ mFFTPoints[i * 4 + 3] = rect.height() - (dbValue * 2 - 10);
+ }
+ }
+
+ mCanvas.drawLines(mFFTPoints, mPaint);
+ }
+}
diff --git a/src/com/pheelicks/visualizer/FFTData.java b/src/com/pheelicks/visualizer/FFTData.java
new file mode 100644
index 0000000..6ae55eb
--- /dev/null
+++ b/src/com/pheelicks/visualizer/FFTData.java
@@ -0,0 +1,12 @@
+package com.pheelicks.visualizer;
+
+// Data class to explicitly indicate that these bytes are the FFT of audio data
+public class FFTData
+{
+ public FFTData(byte[] bytes)
+ {
+ this.bytes = bytes;
+ }
+
+ public byte[] bytes;
+}
diff --git a/src/com/pheelicks/visualizer/Renderer.java b/src/com/pheelicks/visualizer/Renderer.java
new file mode 100644
index 0000000..aa2a56b
--- /dev/null
+++ b/src/com/pheelicks/visualizer/Renderer.java
@@ -0,0 +1,64 @@
+package com.pheelicks.visualizer;
+
+import android.graphics.Canvas;
+import android.graphics.Rect;
+
+abstract public class Renderer
+{
+ // Canvas & Rect to render to
+ protected Canvas mCanvas;
+
+ // Have these as members, so we don't have to re-create them each time
+ protected float[] mPoints;
+ protected float[] mFFTPoints;
+ public Renderer(Canvas canvas)
+ {
+ mCanvas = canvas;
+ }
+
+ // As the display of raw/FFT audio will usually look different, subclasses
+ // will typically only implement one of the below methods
+ /**
+ * Implement this method to render the audio data onto the canvas
+ * @param data - Data to render
+ * @param rect - Rect to render into
+ */
+ abstract public void onRender(AudioData data, Rect rect);
+
+ /**
+ * Implement this method to render the FFT audio data onto the canvas
+ * @param data - Data to render
+ * @param rect - Rect to render into
+ */
+ abstract public void onRender(FFTData data, Rect rect);
+
+
+ // These methods should actually be called for rendering
+ /**
+ * Render the audio data onto the canvas
+ * @param data - Data to render
+ * @param rect - Rect to render into
+ */
+ final public void render(AudioData data, Rect rect)
+ {
+ if (mPoints == null || mPoints.length < data.bytes.length * 4) {
+ mPoints = new float[data.bytes.length * 4];
+ }
+
+ onRender(data, rect);
+ }
+
+ /**
+ * Render the FFT data onto the canvas
+ * @param data - Data to render
+ * @param rect - Rect to render into
+ */
+ final public void render(FFTData data, Rect rect)
+ {
+ if (mFFTPoints == null || mFFTPoints.length < data.bytes.length * 4) {
+ mFFTPoints = new float[data.bytes.length * 4];
+ }
+
+ onRender(data, rect);
+ }
+}
diff --git a/src/com/pheelicks/visualizer/VisualizerActivity.java b/src/com/pheelicks/visualizer/VisualizerActivity.java
index 795e90e..031ac9d 100644
--- a/src/com/pheelicks/visualizer/VisualizerActivity.java
+++ b/src/com/pheelicks/visualizer/VisualizerActivity.java
@@ -18,12 +18,13 @@ public class VisualizerActivity extends Activity {
mPlayer = MediaPlayer.create(this, R.raw.test);
mPlayer.setLooping(true);
+ mPlayer.start();
linkVisualizer(mPlayer);
}
/**
- * Links the visualizer to a player
+ * Links the visualizer to a player
* TODO Refactor this into visualizer
* @param player
*/
@@ -69,6 +70,34 @@ public class VisualizerActivity extends Activity {
});
}
+ // Cleanup
+ @Override
+ protected void onPause()
+ {
+ if (isFinishing() && (mPlayer != null))
+ {
+ mVisualizer.release();
+ mPlayer.release();
+ mPlayer = null;
+ }
+
+ super.onPause();
+ }
+
+ @Override
+ protected void onDestroy()
+ {
+ if (mPlayer != null)
+ {
+ mPlayer.stop();
+ mPlayer.release();
+ mPlayer = null;
+ }
+
+ super.onDestroy();
+ }
+
+ // Actions for buttons defined in xml
public void startPressed(View view)
{
mPlayer.start();
diff --git a/src/com/pheelicks/visualizer/VisualizerView.java b/src/com/pheelicks/visualizer/VisualizerView.java
index 94505b6..82d7100 100644
--- a/src/com/pheelicks/visualizer/VisualizerView.java
+++ b/src/com/pheelicks/visualizer/VisualizerView.java
@@ -35,16 +35,11 @@ class VisualizerView extends View {
private Paint mCirclePaint = new Paint();
private Paint mLinePaint = new Paint();
- private Paint mFFTLineTopPaint = new Paint();
- private Paint mFFTLineBottomPaint = new Paint();
private Paint mSpecialLinePaint = new Paint();
private Paint mProgressLinePaint = new Paint();
private Paint mFlashPaint = new Paint();
private Paint mFadePaint = new Paint();
- final int fft_divis_top = 8; // Set to some factor of 2 to adjust number of FFT bars
- final int fft_divis_bottom = 16; // Set to some factor of 2 to adjust number of FFT bars
-
// Usual BS of 3 constructors
public VisualizerView(Context context, AttributeSet attrs, int defStyle)
{
@@ -81,13 +76,6 @@ class VisualizerView extends View {
mProgressLinePaint.setAntiAlias(true);
mProgressLinePaint.setColor(Color.argb(255, 22, 131, 255));
- mFFTLineTopPaint.setStrokeWidth(fft_divis_top * 3f);
- mFFTLineTopPaint.setAntiAlias(true);
- mFFTLineTopPaint.setColor(Color.argb(200, 233, 0, 44));
-
- mFFTLineBottomPaint.setStrokeWidth(fft_divis_bottom * 3f);
- mFFTLineBottomPaint.setAntiAlias(true);
- mFFTLineBottomPaint.setColor(Color.argb(88, 0, 233, 44));
mFlashPaint.setColor(Color.argb(122, 255, 255, 255));
@@ -134,6 +122,10 @@ class VisualizerView extends View {
Canvas mCanvas;
Random mRandom = new Random();
float amplitude = 0;
+
+ BarGraphRenderer mBarGraphRendererTop;
+ BarGraphRenderer mBarGraphRendererBottom;
+
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
@@ -175,6 +167,17 @@ class VisualizerView extends View {
if(mCanvas == null)
{
mCanvas = new Canvas(mCanvasBitmap);
+ Paint paint = new Paint();
+ paint.setStrokeWidth(50f);
+ paint.setAntiAlias(true);
+ paint.setColor(Color.argb(200, 233, 0, 44));
+ mBarGraphRendererBottom = new BarGraphRenderer(mCanvas, 16, paint, false);
+
+ Paint paint2 = new Paint();
+ paint2.setStrokeWidth(12f);
+ paint2.setAntiAlias(true);
+ paint2.setColor(Color.argb(200, 11, 111, 233));
+ mBarGraphRendererTop = new BarGraphRenderer(mCanvas, 4, paint2, true);
}
mCanvas.drawLines(mPoints, mCirclePaint);
@@ -214,43 +217,10 @@ class VisualizerView extends View {
return;
}
- if (mFFTPoints == null || mFFTPoints.length < mBytes.length * 4) {
- mFFTPoints = new float[mFFTBytes.length * 4];
- }
-
- // Equalizer top
- if(mFFTBytes != null)
- {
- for (int i = 0; i < mFFTBytes.length / fft_divis_top; i++) {
- mFFTPoints[i * 4] = i * 4 * fft_divis_top;
- mFFTPoints[i * 4 + 1] = 0;
- mFFTPoints[i * 4 + 2] = i * 4 * fft_divis_top;
- byte rfk = mFFTBytes[fft_divis_top * i];
- byte ifk = mFFTBytes[fft_divis_top * i + 1];
- float magnitude = (rfk * rfk + ifk * ifk);
- int dbValue = (int) (10 * Math.log10(magnitude));
- mFFTPoints[i * 4 + 3] = (dbValue * 2 - 10);
- }
-
- mCanvas.drawLines(mFFTPoints, mFFTLineTopPaint);
- }
+ FFTData fftData = new FFTData(mFFTBytes);
- // Equalizer bottom
- if(mFFTBytes != null)
- {
- for (int i = 0; i < mFFTBytes.length / fft_divis_bottom; i++) {
- mFFTPoints[i * 4] = i * 4 * fft_divis_bottom;
- mFFTPoints[i * 4 + 1] = mRect.height() - 2;
- mFFTPoints[i * 4 + 2] = i * 4 * fft_divis_bottom;
- byte rfk = mFFTBytes[fft_divis_bottom * i];
- byte ifk = mFFTBytes[fft_divis_bottom * i + 1];
- float magnitude = (rfk * rfk + ifk * ifk);
- int dbValue = (int) (10 * Math.log10(magnitude));
- mFFTPoints[i * 4 + 3] = mRect.height() - (dbValue * 4) - 2;
- }
-
- mCanvas.drawLines(mFFTPoints, mFFTLineBottomPaint);
- }
+ mBarGraphRendererTop.render(fftData, mRect);
+ mBarGraphRendererBottom.render(fftData, mRect);
// We totally need a thing moving along the bottom
float cX = mRect.width()*(SystemClock.currentThreadTimeMillis() - mFlashTime)/mFlashPeriod;