日韩欧美自拍在线观看-欧美精品在线看片一区二区-高清性视频一区二区播放-欧美日韩女优制服另类-国产精品久久久久久av蜜臀-成人在线黄色av网站-肥臀熟妇一区二区三区-亚洲视频在线播放老色-在线成人激情自拍视频

Android應(yīng)用于模擬信號(hào)示波器

出處:尤新亮 發(fā)布于:2011-08-25 22:39:21

    Android一詞的本義指“機(jī)器人”,同時(shí)也是Google于2007年11月5日宣布的基于Linux平臺(tái)的開源手機(jī)操作系統(tǒng)的名稱,該平臺(tái)由操作系統(tǒng)、中間件、用戶界面和應(yīng)用軟件組成,號(hào)稱是為移動(dòng)終端打造的真正開放和完整的移動(dòng)軟件。目前,版本為Android 2.4 Gingerbread和Android 3.0 Honeycomb。

    Android是基于Linux開放性內(nèi)核的操作系統(tǒng),是Google公司在2007年11月5日公布的手機(jī)操作系統(tǒng)。早期由原名為"Android"的公司開發(fā),谷歌在2005年收購(gòu)"Android.Inc"后,繼續(xù)進(jìn)行對(duì)Android系統(tǒng)開發(fā)運(yùn)營(yíng),它采用了軟件堆層(software stack,又名軟件疊層)的架構(gòu),主要分為三部分。底層Linux內(nèi)核只提供基本功能,其他的應(yīng)用軟件則由各公司自行開發(fā),部分程序以Java編寫。

    本文結(jié)合SurfaceView實(shí)現(xiàn)一個(gè)Android版的手機(jī)模擬信號(hào)示波器。近物聯(lián)網(wǎng)炒得很火,作為手機(jī)軟件開發(fā)者,如何在不修改手機(jī)硬件電路的前提下實(shí)現(xiàn)與第三方傳感器結(jié)合呢?麥克風(fēng)就是一個(gè)很好的ADC接口,通過麥克風(fēng)與第三方傳感器結(jié)合,再在軟件里對(duì)模擬信號(hào)做相應(yīng)的處理,就可以提供更豐富的傳感化應(yīng)用。

    先來(lái)看看本文程序運(yùn)行的效果圖:

 

 

 

    本文程序使用8000hz的采樣率,對(duì)X軸方向繪圖的實(shí)時(shí)性要求較高,如果不降低X軸的分辨率,程序的實(shí)時(shí)性較差,因此程序?qū)軸數(shù)據(jù)縮小區(qū)間為8倍~16倍。由于采用16位采樣,因此Y軸數(shù)據(jù)的高度相對(duì)于手機(jī)屏幕來(lái)說也偏大,程序也對(duì)Y軸數(shù)據(jù)做縮小,區(qū)間為1倍~10倍。在SurfaceView的OnTouchListener方法里加入了波形基線的位置調(diào)節(jié),直接在SurfaceView控件上觸摸即可控制整體波形偏上或偏下顯示。

    main.xml源碼如下:

    view plaincopy to clipboardprint?

    android:orientation="vertical" android:layout_width="fill_parent"

    android:layout_height="fill_parent">

    android:layout_height="wrap_content" android:layout_width="fill_parent"

    android:orientation="horizontal">

        
        


    android:layout_height="wrap_content" android:id="@+id/zctlX">

    android:layout_height="wrap_content" android:id="@+id/zctlY">

    android:layout_height="fill_parent" android:layout_width="fill_parent">

    android:orientation="vertical" android:layout_width="fill_parent"

    android:layout_height="fill_parent">

    android:layout_height="wrap_content" android:layout_width="fill_parent"

    android:orientation="horizontal">  


  


    android:layout_height="wrap_content" android:id="@+id/zctlX">

    android:layout_height="wrap_content" android:id="@+id/zctlY">

    android:layout_height="fill_parent" android:layout_width="fill_parent">

    ClsOscilloscope.java是實(shí)現(xiàn)示波器的類庫(kù),包含AudioRecord操作線程和SurfaceView繪圖線程的實(shí)現(xiàn),兩個(gè)線程同步操作,代碼如下:

    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 inBuf = new ArrayList();

    private boolean isRecording = false;// 線程控制標(biāo)記

    /**

    * 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() {

    isRecording = false;

    inBuf.clear();// 清除

    }

    /**

    * 負(fù)責(zé)從MIC保存數(shù)據(jù)到inBuf

    *

    * @author GV

    *

    */

    class RecordThread extends Thread {

    private int recBufSize;

    private AudioRecord audioRecord;

    public RecordThread(AudioRecord audioRecord, int recBufSize) {

    this.audioRecord = audioRecord;

    this.recBufSize = recBufSize;

    }

    public void run() {

    try {

    short[] buffer = new short[recBufSize];

    audioRecord.startRecording();// 開始錄制

    while (isRecording) {

    // 從MIC保存數(shù)據(jù)到緩沖區(qū)

    int bufferReadResult = audioRecord.read(buffer, 0,

    recBufSize);

    short[] tmpBuf = new short[bufferReadResult / rateX];

    for (int i = 0, ii = 0; i < tmpBuf.length; i++, ii = i

    * rateX) {

    tmpBuf[i] = buffer[ii];

    }

    synchronized (inBuf) {//

    inBuf.add(tmpBuf);// 添加數(shù)據(jù)

    }

    }

    audioRecord.stop();

    } catch (Throwable t) {

    }

    }

    };

    /**

    * 負(fù)責(zé)繪制inBuf中的數(shù)據(jù)

    *

    * @author GV

    *

    */

    class DrawThread extends Thread {

    private int oldX = 0;// 上次繪制的X坐標(biāo)

    private int oldY = 0;// 上次繪制的Y坐標(biāo)

    private SurfaceView sfv;// 畫板

    private int X_index = 0;// 當(dāng)前畫圖所在屏幕X軸的坐標(biāo)

    private Paint mPaint;// 畫筆

    public DrawThread(SurfaceView sfv, Paint mPaint) {

    this.sfv = sfv;

    this.mPaint = mPaint;

    }

    public void run() {

    while (isRecording) {

    ArrayList buf = new ArrayList();

    synchronized (inBuf) {

    if (inBuf.size() == 0)

    continue;

    buf = (ArrayList) inBuf.clone();// 保存

    inBuf.clear();// 清除

    }

    for (int i = 0; i < buf.size(); i++) {

    short[] tmpBuf = buf.get(i);

    SimpleDraw(X_index, tmpBuf, rateY, baseLine);// 把緩沖區(qū)數(shù)據(jù)畫出來(lái)

    X_index = X_index + tmpBuf.length;

    if (X_index > sfv.getWidth()) {

    X_index = 0;

    }

    }

    }

    }

    /**

    * 繪制指定區(qū)域

    *

    * @param start

    *            X軸開始的位置(全屏)

    * @param buffer

    *            緩沖區(qū)

    * @param rate

    *            Y軸數(shù)據(jù)縮小的比例

    * @param baseLine

    *            Y軸基線

    */

    void SimpleDraw(int start, short[] buffer, int rate, int baseLine) {

    if (start == 0)

    oldX = 0;

    Canvas canvas = sfv.getHolder()。lockCanvas(

    new Rect(start, 0, start + buffer.length, sfv.getHeight()));// 關(guān)鍵:獲取畫布

    canvas.drawColor(Color.BLACK);// 清除背景

    int y;

    for (int i = 0; i < buffer.length; i++) {// 有多少畫多少

    int x = i + start;

    y = buffer[i] / rate + baseLine;// 調(diào)節(jié)縮小比例,調(diào)節(jié)基準(zhǔn)線

    canvas.drawLine(oldX, oldY, x, y, mPaint);

    oldX = x;

    oldY = y;

    }

    sfv.getHolder()。unlockCanvasAndPost(canvas);// 解鎖畫布,提交畫好的圖像

    }

    }

    }

    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 inBuf = new ArrayList();

    private boolean isRecording = false;// 線程控制標(biāo)記

    /**

    * 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() {

    isRecording = false;

    inBuf.clear();// 清除

    }

    /**

    * 負(fù)責(zé)從MIC保存數(shù)據(jù)到inBuf

    *

    * @author GV

    *

    */

    class RecordThread extends Thread {

    private int recBufSize;

    private AudioRecord audioRecord;

    public RecordThread(AudioRecord audioRecord, int recBufSize) {

    this.audioRecord = audioRecord;

    this.recBufSize = recBufSize;

    }

    public void run() {

    try {

    short[] buffer = new short[recBufSize];

    audioRecord.startRecording();// 開始錄制

    while (isRecording) {

    // 從MIC保存數(shù)據(jù)到緩沖區(qū)

    int bufferReadResult = audioRecord.read(buffer, 0,

    recBufSize);

    short[] tmpBuf = new short[bufferReadResult / rateX];

    for (int i = 0, ii = 0; i < tmpBuf.length; i++, ii = i

    * rateX) {

    tmpBuf[i] = buffer[ii];

    }

    synchronized (inBuf) {//

    inBuf.add(tmpBuf);// 添加數(shù)據(jù)

    }

    }

    audioRecord.stop();

    } catch (Throwable t) {

    }

    }

    };

    /**

    * 負(fù)責(zé)繪制inBuf中的數(shù)據(jù)

    *

    * @author GV

    *

    */

    class DrawThread extends Thread {

    private int oldX = 0;// 上次繪制的X坐標(biāo)

    private int oldY = 0;// 上次繪制的Y坐標(biāo)

    private SurfaceView sfv;// 畫板

    private int X_index = 0;// 當(dāng)前畫圖所在屏幕X軸的坐標(biāo)

    private Paint mPaint;// 畫筆

    public DrawThread(SurfaceView sfv, Paint mPaint) {

    this.sfv = sfv;

    this.mPaint = mPaint;

    }

    public void run() {

    while (isRecording) {

    ArrayList buf = new ArrayList();

    synchronized (inBuf) {

    if (inBuf.size() == 0)

    continue;

    buf = (ArrayList) inBuf.clone();// 保存

    inBuf.clear();// 清除

    }

    for (int i = 0; i < buf.size(); i++) {

    short[] tmpBuf = buf.get(i);

    SimpleDraw(X_index, tmpBuf, rateY, baseLine);// 把緩沖區(qū)數(shù)據(jù)畫出來(lái)

    X_index = X_index + tmpBuf.length;

    if (X_index > sfv.getWidth()) {

    X_index = 0;

    }

    }

    }

    }

    /**

    * 繪制指定區(qū)域

    *

    * @param start

    *            X軸開始的位置(全屏)

    * @param buffer

    *            緩沖區(qū)

    * @param rate

    *            Y軸數(shù)據(jù)縮小的比例

    * @param baseLine

    *            Y軸基線

    */

    void SimpleDraw(int start, short[] buffer, int rate, int baseLine) {

    if (start == 0)

    oldX = 0;

    Canvas canvas = sfv.getHolder()。lockCanvas(

    new Rect(start, 0, start + buffer.length, sfv.getHeight()));// 關(guān)鍵:獲取畫布

    canvas.drawColor(Color.BLACK);// 清除背景

    int y;

    for (int i = 0; i < buffer.length; i++) {// 有多少畫多少

    int x = i + start;

    y = buffer[i] / rate + baseLine;// 調(diào)節(jié)縮小比例,調(diào)節(jié)基準(zhǔn)線

    canvas.drawLine(oldX, oldY, x, y, mPaint);

    oldX = x;

    oldY = y;

    }

    sfv.getHolder()。unlockCanvasAndPost(canvas);// 解鎖畫布,提交畫好的圖像

    }

    }

    }

    testOscilloscope.java是主程序,控制UI和ClsOscilloscope,代碼如下:

    view plaincopy to clipboardprint?

    package com.testOscilloscope;

    import android.app.Activity;

    import android.graphics.Color;

    import android.graphics.Paint;

    import android.media.AudioFormat;

    import android.media.AudioRecord;

    import android.media.MediaRecorder;

    import android.os.Bundle;

    import android.view.MotionEvent;

    import android.view.SurfaceView;

    import android.view.View;

    import android.view.View.OnTouchListener;

    import android.widget.Button;

    import android.widget.ZoomControls;

    public class testOscilloscope extends Activity {

    /** Called when the activity is first created. */

    Button btnStart,btnExit;

    SurfaceView sfv;

    ZoomControls zctlX,zctlY;

    ClsOscilloscope clsOscilloscope=new ClsOscilloscope();

    static final int frequency = 8000;//分辨率

    static final int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;

    static final int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;

    static final int xMax = 16;//X軸縮小比例值,X軸數(shù)據(jù)量巨大,容易產(chǎn)生刷新延時(shí)

    static final int xMin = 8;//X軸縮小比例值

    static final int yMax = 10;//Y軸縮小比例值

    static final int yMin = 1;//Y軸縮小比例值

    int recBufSize;//錄音buffer大小

    AudioRecord audioRecord;

    Paint mPaint;

    @Override

    public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    //錄音組件

    recBufSize = AudioRecord.getMinBufferSize(frequency,

    channelConfiguration, audioEncoding);

    audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, frequency,

    channelConfiguration, audioEncoding, recBufSize);

    //按鍵

    btnStart = (Button) this.findViewById(R.id.btnStart);

    btnStart.setOnClickListener(new ClickEvent());

    btnExit = (Button) this.findViewById(R.id.btnExit);

    btnExit.setOnClickListener(new ClickEvent());

    //畫板和畫筆

    sfv = (SurfaceView) this.findViewById(R.id.SurfaceView01);

    sfv.setOnTouchListener(new TouchEvent());

    mPaint = new Paint();

    mPaint.setColor(Color.GREEN);// 畫筆為綠色

    mPaint.setStrokeWidth(1);// 設(shè)置畫筆粗細(xì)

    //示波器類庫(kù)

    clsOscilloscope.initOscilloscope(xMax/2, yMax/2, sfv.getHeight()/2);

    //縮放控件,X軸的數(shù)據(jù)縮小的比率高些

    zctlX = (ZoomControls)this.findViewById(R.id.zctlX);

    zctlX.setOnZoomInClickListener(new View.OnClickListener() {

    @Override

    public void onClick(View v) {

    if(clsOscilloscope.rateX>xMin)

    clsOscilloscope.rateX--;

    setTitle("X軸縮小"+String.valueOf(clsOscilloscope.rateX)+"倍"

    +","+"Y軸縮小"+String.valueOf(clsOscilloscope.rateY)+"倍");

    }

    });

    zctlX.setOnZoomOutClickListener(new View.OnClickListener() {

    @Override

    public void onClick(View v) {

    if(clsOscilloscope.rateX                    clsOscilloscope.rateX++;

    setTitle("X軸縮小"+String.valueOf(clsOscilloscope.rateX)+"倍"

    +","+"Y軸縮小"+String.valueOf(clsOscilloscope.rateY)+"倍");

    }

    });

    zctlY = (ZoomControls)this.findViewById(R.id.zctlY);

    zctlY.setOnZoomInClickListener(new View.OnClickListener() {

    @Override

    public void onClick(View v) {

    if(clsOscilloscope.rateY>yMin)

    clsOscilloscope.rateY--;

    setTitle("X軸縮小"+String.valueOf(clsOscilloscope.rateX)+"倍"

    +","+"Y軸縮小"+String.valueOf(clsOscilloscope.rateY)+"倍");

    }

    });

    zctlY.setOnZoomOutClickListener(new View.OnClickListener() {

    @Override

    public void onClick(View v) {

    if(clsOscilloscope.rateY                    clsOscilloscope.rateY++;

    setTitle("X軸縮小"+String.valueOf(clsOscilloscope.rateX)+"倍"

    +","+"Y軸縮小"+String.valueOf(clsOscilloscope.rateY)+"倍");

    }

    });

    }

    @Override

    protected void onDestroy() {

    super.onDestroy();

    android.os.Process.killProcess(android.os.Process.myPid());

    }

    /**

    * 按鍵事件處理

    * @author GV

    *

    */

    class ClickEvent implements View.OnClickListener {

    @Override

    public void onClick(View v) {

    if (v == btnStart) {

    clsOscilloscope.baseLine=sfv.getHeight()/2;

    clsOscilloscope.Start(audioRecord,recBufSize,sfv,mPaint);

    } else if (v == btnExit) {

    clsOscilloscope.Stop();

    }

    }

    }

    /**

    * 觸摸屏動(dòng)態(tài)設(shè)置波形圖基線

    * @author GV

    *

    */

    class TouchEvent implements OnTouchListener{

    @Override

    public boolean onTouch(View v, MotionEvent event) {

    clsOscilloscope.baseLine=(int)event.getY();

    return true;

    }

    }

    }


  

版權(quán)與免責(zé)聲明

凡本網(wǎng)注明“出處:維庫(kù)電子市場(chǎng)網(wǎng)”的所有作品,版權(quán)均屬于維庫(kù)電子市場(chǎng)網(wǎng),轉(zhuǎn)載請(qǐng)必須注明維庫(kù)電子市場(chǎng)網(wǎng),http://www.hbjingang.com,違反者本網(wǎng)將追究相關(guān)法律責(zé)任。

本網(wǎng)轉(zhuǎn)載并注明自其它出處的作品,目的在于傳遞更多信息,并不代表本網(wǎng)贊同其觀點(diǎn)或證實(shí)其內(nèi)容的真實(shí)性,不承擔(dān)此類作品侵權(quán)行為的直接責(zé)任及連帶責(zé)任。其他媒體、網(wǎng)站或個(gè)人從本網(wǎng)轉(zhuǎn)載時(shí),必須保留本網(wǎng)注明的作品出處,并自負(fù)版權(quán)等法律責(zé)任。

如涉及作品內(nèi)容、版權(quán)等問題,請(qǐng)?jiān)谧髌钒l(fā)表之日起一周內(nèi)與本網(wǎng)聯(lián)系,否則視為放棄相關(guān)權(quán)利。

廣告
OEM清單文件: OEM清單文件
*公司名:
*聯(lián)系人:
*手機(jī)號(hào)碼:
QQ:
有效期:

掃碼下載APP,
一鍵連接廣大的電子世界。

在線人工客服

買家服務(wù):
賣家服務(wù):
技術(shù)客服:

0571-85317607

網(wǎng)站技術(shù)支持

13606545031

客服在線時(shí)間周一至周五
9:00-17:30

關(guān)注官方微信號(hào),
第一時(shí)間獲取資訊。

建議反饋

聯(lián)系人:

聯(lián)系方式:

按住滑塊,拖拽到最右邊
>>
感謝您向阿庫(kù)提出的寶貴意見,您的參與是維庫(kù)提升服務(wù)的動(dòng)力!意見一經(jīng)采納,將有感恩紅包奉上哦!