首页 > 程序开发 > 移动开发 > Android >

Android提高第十一篇之模拟信号示波器

2011-01-10

上次简单地介绍了AudioRecord和AudioTrack的使用,这次就结合SurfaceView实现一个Android版的手机模拟信号示波器(PS:以前也讲过J2ME版的手机示波器)。最近物联网炒得很火,作为手机软件开发者,如何在不修改手机硬件电路的前提下实现与

上次简单地介绍了AudioRecord和AudioTrack的使用,这次就结合SurfaceView实现一个Android版的手机模拟信号示波器(PS:以前也讲过J2ME版的手机示波器)。最近物联网炒得很火,作为手机软件开发者,如何在不修改手机硬件电路的前提下实现与第三方传感器结合呢?麦克风就是一个很好的ADC接口,通过麦克风与第三方传感器结合,再在软件里对模拟信号做相应的处理,就可以提供更丰富的传感化应用。

先来看看本文程序运行的效果图(屏幕录像速度较慢,真机实际运行起来会更加流畅):

\

本文程序使用8000hz的采样率,对X轴方向绘图的实时性要求较高,如果不降低X轴的分辨率,程序的实时性较差,因此程序对X轴数据缩小区间为8倍~16倍。由于采用16位采样,因此Y轴数据的高度相对于手机屏幕来说也偏大,程序也对Y轴数据做缩小,区间为1倍~10倍。在SurfaceView的OnTouchListener方法里加入了波形基线的位置调节,直接在SurfaceView控件上触摸即可控制整体波形偏上或偏下显示。

main.xml源码如下:

view plaincopy to clipboardprint?
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout android:id="@+id/LinearLayout01"
android:layout_height="wrap_content" android:layout_width="fill_parent"
android:orientation="horizontal">
<Button android:layout_height="wrap_content" android:id="@+id/btnStart"
android:text="开始" android:layout_width="80dip"></Button>
<Button android:layout_height="wrap_content" android:text="停止"
android:id="@+id/btnExit" android:layout_width="80dip"></Button>
<ZoomControls android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="@+id/zctlX"></ZoomControls>
<ZoomControls android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="@+id/zctlY"></ZoomControls>
</LinearLayout>
<SurfaceView android:id="@+id/SurfaceView01"
android:layout_height="fill_parent" android:layout_width="fill_parent"></SurfaceView>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout android:id="@+id/LinearLayout01"
android:layout_height="wrap_content" android:layout_width="fill_parent"
android:orientation="horizontal">
<Button android:layout_height="wrap_content" android:id="@+id/btnStart"
android:text="开始" android:layout_width="80dip"></Button>
<Button android:layout_height="wrap_content" android:text="停止"
android:id="@+id/btnExit" android:layout_width="80dip"></Button>
<ZoomControls android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="@+id/zctlX"></ZoomControls>
<ZoomControls android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="@+id/zctlY"></ZoomControls>
</LinearLayout>
<SurfaceView android:id="@+id/SurfaceView01"
android:layout_height="fill_parent" android:layout_width="fill_parent"></SurfaceView>
</LinearLayout>

ClsOscilloscope.java是实现示波器的类库,包含AudioRecord操作线程和SurfaceView绘图线程的实现,两个线程同步操作,代码如下:

view plaincopy to clipboardprint?
package com.testOscilloscope;
import java.util.ArrayList;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.media.AudioRecord;
import android.view.SurfaceView;
public class ClsOscilloscope {
private ArrayList<short[]> inBuf = new ArrayList<short[]>();
private boolean isRecording = false;// 线程控制标记
/**
* X轴缩小的比例
*/
public int rateX = 4;
/**
* Y轴缩小的比例
*/
public int rateY = 4;
/**
* Y轴基线
*/
public int baseLine = 0;
/**
* 初始化
*/
public void initOscilloscope(int rateX, int rateY, int baseLine) {
this.rateX = rateX;
this.rateY = rateY;
this.baseLine = baseLine;
}
/**
* 开始
*
* @param recBufSize
* AudioRecord的MinBufferSize
*/
public void Start(AudioRecord audioRecord, int recBufSize, SurfaceView sfv,
Paint mPaint) {
isRecording = true;
new RecordThread(audioRecord, recBufSize).start();// 开始录制线程
new DrawThread(sfv, mPaint).start();// 开始绘制线程
}
/**
* 停止
*/
public void Stop() {
isRecordi

热点推荐