• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.mobileer.oboetester;
18 
19 import android.content.Context;
20 import android.content.res.Resources;
21 import android.content.res.TypedArray;
22 import android.graphics.Canvas;
23 import android.graphics.Color;
24 import android.graphics.Paint;
25 import android.util.AttributeSet;
26 import android.view.View;
27 
28 /**
29  * Display an audio waveform in a custom View.
30  */
31 public class WaveformView extends View {
32     private static final float MESSAGE_TEXT_SIZE = 80;
33     private Paint mWavePaint;
34     private Paint mBackgroundPaint;
35     private Paint mMessagePaint;
36     private int mCurrentWidth;
37     private int mCurrentHeight;
38     private float[] mData;
39     private int mSampleCount;
40     private int mSampleOffset;
41     private float mOffsetY;
42     private float mScaleY;
43     private int[] mCursors;
44     private String mMessage;
45     private Paint mCursorPaint;
46 
WaveformView(Context context, AttributeSet attrs)47     public WaveformView(Context context, AttributeSet attrs) {
48         super(context, attrs);
49         TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
50                 R.styleable.WaveformView, 0, 0);
51         init();
52     }
53     @SuppressWarnings("deprecation")
init()54     private void init() {
55         Resources res = getResources();
56 
57         mWavePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
58         mWavePaint.setColor(res.getColor(R.color.waveform_line));
59         float strokeWidth = res.getDimension(R.dimen.waveform_stroke_width);
60         mWavePaint.setStrokeWidth(strokeWidth);
61 
62         mCursorPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
63         mCursorPaint.setColor(Color.RED);
64         mCursorPaint.setStrokeWidth(3.0f);
65 
66         mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
67         mBackgroundPaint.setColor(res.getColor(R.color.waveform_background));
68         mBackgroundPaint.setStyle(Paint.Style.FILL);
69 
70         mMessagePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
71         mMessagePaint.setColor(res.getColor(R.color.waveform_line));
72         mMessagePaint.setTextSize(MESSAGE_TEXT_SIZE);
73     }
74 
75     @Override
onSizeChanged(int w, int h, int oldw, int oldh)76     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
77         mCurrentWidth = w;
78         mCurrentHeight = h;
79         mOffsetY = 0.5f * h;
80         mScaleY = 0.0f - mOffsetY;
81     }
82 
getMessage()83     public String getMessage() {
84         return mMessage;
85     }
86 
87     /**
88      * Set message to be displayed over the waveform.
89      * Set null for no message.
90      * @param message text or null
91      */
setMessage(String message)92     public void setMessage(String message) {
93         this.mMessage = message;
94     }
95 
96     @Override
onDraw(Canvas canvas)97     protected void onDraw(Canvas canvas) {
98         super.onDraw(canvas);
99         float [] localData = mData;
100         canvas.drawRect(0.0f, 0.0f, mCurrentWidth,
101                 mCurrentHeight, mBackgroundPaint);
102         if (mMessage != null) {
103             canvas.drawText(mMessage, 20, mCurrentHeight - 20, mMessagePaint);
104         }
105         if (localData == null || mSampleCount == 0) {
106             return;
107         }
108         float xScale = ((float) mCurrentWidth) / (mSampleCount - 1);
109         float x0 = 0.0f;
110         if (xScale < 1.0) {
111             // Draw a vertical bar for multiple samples.
112             float ymin = mOffsetY;
113             float ymax = mOffsetY;
114             for (int i = 0; i < mSampleCount; i++) {
115                 float x1 = i * xScale;
116                 if ((int) x0 != (int) x1) {
117                     // draw old data
118                     canvas.drawLine(x0, ymin, x0, ymax, mWavePaint);
119                     x0 = x1;
120                     ymin = mOffsetY;
121                     ymax = mOffsetY;
122                 }
123                 float y1 = (localData[i] * mScaleY) + mOffsetY;
124                 ymin = Math.min(ymin, y1);
125                 ymax = Math.max(ymax, y1);
126             }
127         } else {
128             // Draw line between samples.
129             float y0 = (localData[0] * mScaleY) + mOffsetY;
130             for (int i = 1; i < mSampleCount; i++) {
131                 float x1 = i * xScale;
132                 float y1 = (localData[i] * mScaleY) + mOffsetY;
133                 canvas.drawLine(x0, y0, x1, y1, mWavePaint);
134                 x0 = x1;
135                 y0 = y1;
136             }
137         }
138         if (mCursors != null) {
139             for (int i = 0; i < mCursors.length; i++) {
140                 float x = mCursors[i] * xScale;
141                 canvas.drawLine(x, 0, x, mCurrentHeight, mCursorPaint);
142             }
143         }
144     }
145 
146     /**
147      * Copy data into internal buffer then repaint.
148      */
setSampleData(float[] samples)149     public void setSampleData(float[] samples) {
150         setSampleData(samples, 0, samples.length);
151     }
152 
setSampleData(float[] samples, int offset, int count)153     public void setSampleData(float[] samples, int offset, int count) {
154         if ((offset+count) > samples.length) {
155             throw new IllegalArgumentException("Exceed array bounds. ("
156                     + offset + " + " + count + ") > " + samples.length);
157         }
158         if (mData == null || count > mData.length) {
159             mData = new float[count];
160         }
161         System.arraycopy(samples, offset, mData, 0, count);
162         mSampleCount = count;
163         mSampleOffset = offset;
164     }
165 
clearSampleData()166     public void clearSampleData() {
167         mData = null;
168         mSampleCount = 0;
169         mSampleOffset = 0;
170     }
171 
172     /**
173      * Copy cursor positions into internal buffer then repaint.
174      */
setCursorData(int[] cursors)175     public void setCursorData(int[] cursors) {
176         if (cursors == null) {
177             mCursors = null;
178         } else {
179             if (mCursors == null || cursors.length != mCursors.length) {
180                 mCursors = new int[cursors.length];
181             }
182             System.arraycopy(cursors, 0, mCursors, 0, mCursors.length);
183         }
184     }
185 }
186