android声⾳传感器编程这篇整理了⼀些关于android声⾳传感器部分的处理的代码
代码收集整理⾃⽹络
主要原因是因为何畅最近在做的项⽬
帮他整理的
部分代码我加亮注释应该可读性还不错
排版始终有问题
不过不影响可读性
就算了
暂时就先这样了
下⾯是代码部分
有不懂的可以留⾔
也可以⼀起讨论交流
下⾯代码调⽤声⾳传感器
获取声⾳信号
从⽽获取⾳量
01 package eoe . demo;
03 dia.AudioFormat;
04 dia.AudioRecord;
05 dia.MediaRecorder;
06 import android.util.Log;
08 public class RecordThread extends Thread {
09 private AudioRecord ar;
10 private int bs;
11 private static int SAMPLE_RATE_IN_HZ = 8000;
12 private boolean isRun = false;
13 public RecordThread() {
14 super();
15 bs = AudioRecord . getMinBufferSize( SAMPLE_RATE_IN_HZ , AudioFormat . CHANNEL_CONFIGURATION_MONO ,
AudioFormat . ENCODING_PCM_16BIT);
16 ar = new AudioRecord( MediaRecorder . AudioSource . MIC , SAMPLE_RATE_IN_HZ , AudioFormat .
CHANNEL_CONFIGURATION_MONO , AudioFormat . ENCODING_PCM_16BIT , bs);
17 }
18 public void run() {
19 super . run();
20 ar . startRecording();
android编程入门指南 pdf
21 // ⽤于读取的
22 buffer byte [] buffer = new byte [bs ]; isRun = true; while ( isRun) {
23 int r = ar . read( buffer , 0 , bs);
24 int v = 0;
25 // 将 buffer 内容取出,进⾏平⽅和运算
26 for ( int i = 0; i < buffer . length; i ++) {
27 // 这⾥没有做运算的优化,为了更加清晰的展⽰代码
28 v += buffer [ i ] * buffer [ i ];
29 }
30 // 平⽅和除以数据总长度,得到⾳量⼤⼩。可以获取⽩噪声值,然后对实际采样进⾏标准化。
31 // 如果想利⽤这个数值进⾏操作,建议⽤ sendMessage 将其抛出,在 Handler ⾥进⾏处理。
32 Log . d( “spl” , String . valueOf( v / ( float) r));
33 }
34 ar . stop();
35 }
36 public void pause() {
37 // 在调⽤本线程的 Activity 的 onPause ⾥调⽤,以便 Activity 暂停时释放麦克风
38 isRun = false;
39 }
40 public void start() {
41 // 在调⽤本线程的 Activity 的 onResume ⾥调⽤,以便 Activity 恢复后继续获取麦克风输⼊⾳量
42 if (! isRun) {
43 super . start();
44 }
45 }
46
47 }
上⾯代码获取的是⼀段时间的⾳量平均值
适合⽤于编写⼀些靠吹⽓控制软件动作的软件
⽽何畅需要根据⾳量来⽣成图像
那么需要的是瞬时⾳量数据
改时间⽚段代码就可以了
鉴于这种运⽤相对少⼀些就不专门贴代码了
再贴⼀个⽰波器代码
本程序使⽤8000hz的采样率,对X轴⽅向绘图的实时性要求较⾼,如果不降低X轴的分辨率,程序的实时性较差,因此程序对X轴数据缩⼩区间为8倍~16倍。由于采⽤16位采样,因此Y轴数据的⾼度相对于⼿机屏幕来说也偏⼤,程序也对Y轴数据做缩⼩,区间为1倍~10倍。在SurfaceView的OnTouchListener⽅法⾥加⼊了波形基线的位置调节,直接在SurfaceView控件上触摸即可控制整体波形偏上或偏下显⽰。
01<?xml version=”1.0″ encoding=”utf-8″?>
02<LinearLayout xmlns:android=“schemas.android/apk/res/android”
03android:orientation=“vertical”android:layout_width=“fill_parent”
04android:layout_height=“fill_parent”>
05<LinearLayout android:id=“@+id/LinearLayout01″
06android:layout_height=“wrap_content”android:layout_width=“fill_parent”
07android:orientation=“horizontal”>
08<Button android:layout_height=“wrap_content”android:id=“@+id/btnStart”
09android:text=“开始”android:layout_width=“80dip”></Button>
10<Button android:layout_height=“wrap_content”android:text=“停⽌”
11android:id=“@+id/btnExit”android:layout_width=“80dip”></Button>
12<ZoomControls android:layout_width=“wrap_content”
13android:layout_height=“wrap_content”android:id=“@+id/zctlX”></ZoomControls>
14<ZoomControls android:layout_width=“wrap_content”
15android:layout_height=“wrap_content”android:id=“@+id/zctlY”></ZoomControls>
16</LinearLayout>
17<SurfaceView android:id=“@+id/SurfaceView01″
18android:layout_height=“fill_parent”android:layout_width=“fill_parent”></SurfaceView>
19</LinearLayout>
ClsOscilloscope.java是实现⽰波器的类库,包含AudioRecord操作线程和SurfaceView绘图线程的实现,两个线程同步操作,代码如下:
001 package com . testOscilloscope; 002 import java.util.ArrayList; 003 aphics.Canvas; 004 import
{ 010    private ArrayList < short []> inBuf = new ArrayList < short []>(); 011    private boolean isRecording = false; // 线程控制标记    012    /**  013      * X轴缩⼩的⽐例  014      */ 015    public int rateX = 4; 016    /**  017      * Y轴缩⼩的⽐例  018      */ 019    public int rateY = 4; 020    /**  021      * Y 轴基线  022      */ 023    public int baseLine = 0; 024    /**  025      * 初始化  026      */ 027    public void initOscilloscope( int rateX , int rateY , int baseLine) { 028        this . rateX = rateX; 029        this . rateY = rateY; 030        this . baseLine = baseLine; 031    } 032    /** 033      * 开始  034      *  035      * @param recBufSize  036      *            AudioRecord的MinBufferSize  037      */ 038    public void Start( AudioRecord audioRecord , int recBufSize , SurfaceView sfv , 039            Paint mPaint) { 040        isRecording = true; 041        new RecordThread( audioRecord , recBufSize ). start(); // 开始录制线程    042        new DrawThread( sfv , mPaint ). start(); // 开始绘制线程    043    } 044    /**  045      * 停⽌  046      */ 047    public void Stop() { 048        isRecording = false; 049        inBuf . clear(); // 清除050    } 051    /**  052      * 负责从MIC保存数据到inBuf  053      *  054      * @author GV  055      *  056      */ 057    class
RecordThread extends Thread { 058        private int recBufSize; 059        private AudioRecord audioRecord; 060        public RecordThread( AudioRecord audioRecord , int recBufSize) { 061            this . audioRecord = audioRecord; 062            this .
recBufSize = recBufSize; 063        } 064        public void run() { 065            try { 066                short [] buffer = new short [ recBufSize ];
067                audioRecord . startRecording(); // 开始录制    068                while ( isRecording) { 069                    // 从MIC保存数据到缓冲区    070                    int bufferReadResult = audioRecord . read( buffer , 0 , 071                            recBufSize); 072                    short [] tmpBuf = new short [ bufferReadResult / rateX ]; 073                    for ( int i = 0 , ii = 0; i < tmpBuf . length; i ++, ii = i 074                            * rateX) { 075                        tmpBuf [ i ] = buffer [ ii ]; 076                    } 077                    synchronized ( inBuf) { //    078                        inBuf .
add( tmpBuf); // 添加数据    079                    } 080                } 081                audioRecord . stop(); 082            } catch ( Throwable t) { 083            } 084        } 085    }; 086    /**  087      * 负责绘制inBuf中的数据  088      *  089      * @author GV  090      *  091      */ 092    class DrawThread extends Thread { 093        private int oldX = 0; // 上次绘制的X坐标    094        private int oldY = 0; // 上次绘制的Y坐标095        private SurfaceView sfv; // 画板    096        private int X_index = 0; // 当前画图所在屏幕X轴的坐标    097        private Paint mPaint; // 画笔    098        public DrawThread( SurfaceView sfv , Paint mPaint) { 099            this . sfv = sfv; 100            this . mPaint = mPaint; 101        } 102        public void run() { 103            while ( isRecording) { 104                ArrayList < short []> buf = new ArrayList < short
[]>(); 105                synchronized ( inBuf) { 106                    if ( inBuf . size() == 0) 107                        continue; 108                    buf = ( ArrayList < short []>) inBuf . clone(); // 保存    109                    inBuf . clear(); // 清除    110                } 111                for ( int i = 0; i < buf .
size(); i ++) { 112                    short [] tmpBuf = buf . get( i); 113                    SimpleDraw( X_index , tmpBuf , rateY , baseLine); // 把缓冲区数据画出来    114                    X_index = X_index + tmpBuf . length; 115                    if ( X_index > sfv . getWidth()) { 116
X_index = 0; 117                    } 118                } 119            } 120        } 121        /**  122          * 绘制指定区域  123          *  124          * @param start  125          *            X轴开始的位置(全屏)  126          * @param buffer  127          *            缓冲区  128          * @param rate  129          *            Y轴数据缩⼩的⽐例  130          * @param baseLine  131          *            Y轴基线  132          */ 133        void SimpleDraw( int start , short [] buffer , int rate , int baseLine) { 134            if ( start == 0) 135                oldX = 0; 136            Canvas canvas = sfv . getHolder (). lockCanvas( 137                    new Rect( start , 0 , start + buffer . length , sfv . getHeight())); // 关键:获取画布    138            canvas . drawColor( Color . BLACK); // 清除背景    139            int y; 140            for ( int i = 0; i < buffer . length; i ++) { //有多少画多少    141                int x = i + start; 142                y = buffer [ i ] / rate + baseLine; // 调节缩⼩⽐例,调节基准线    143                canvas . drawLine( oldX , oldY , x , y , mPaint); 144         
      oldX = x; 145                oldY = y; 146            } 147            sfv . getHolder ().
unlockCanvasAndPost( canvas); // 解锁画布,提交画好的图像    148        } 149    } 150 }
testOscilloscope.java是主程序,控制UI和ClsOscilloscope,代码如下:
001package com . testOscilloscope;
002import android.app.Activity;
aphics.Color;
aphics.Paint;
dia.AudioFormat;
dia.AudioRecord;
dia.MediaRecorder;
008import android.os.Bundle;
009import android.view.MotionEvent;
010import android.view.SurfaceView;
011import android.view.View;
012import android.view.View.OnTouchListener;
013import android.widget.Button;
014import android.widget.ZoomControls;
015public class testOscilloscope extends Activity {
016/** Called when the activity is first created. */
016/** Called when the activity is first created. */
017    Button btnStart , btnExit;
018    SurfaceView sfv;
019    ZoomControls zctlX , zctlY;
020
021    ClsOscilloscope clsOscilloscope = new ClsOscilloscope();
022
023static final int f requency = 8000; //分辨率
024static final int channelConfiguration = AudioFormat . CHANNEL_CONFIGURATION_MONO; 025static final int audioEncoding = AudioFormat . ENCODING_PCM_16BIT;
026static final int xMax = 16; //X轴缩⼩⽐例最⼤值,X轴数据量巨⼤,容易产⽣刷新延时
027static final int xMin = 8; //X轴缩⼩⽐例最⼩值
028static final int yMax = 10; //Y轴缩⼩⽐例最⼤值
029static final int yMin = 1; //Y轴缩⼩⽐例最⼩值
030
031int recBufSize; //录⾳最⼩buffer⼤⼩
032    AudioRecord audioRecord;
033    Paint mPaint;
034    @Override
035public void onCreate( Bundle savedInstanceState) {
036super . onCreate( savedInstanceState);
037        setContentView( R . layout . main);
038//录⾳组件
039        recBufSize = AudioRecord . getMinBufferSize( frequency ,
040                channelConfiguration , audioEncoding);
041        audioRecord = new AudioRecord( MediaRecorder . AudioSource . MIC , frequency ,
042                channelConfiguration , audioEncoding , recBufSize);
043//按键
044        btnStart = ( Button) this . findViewById( R . id . btnStart);
045        btnStart . setOnClickListener( new ClickEvent());
046        btnExit = ( Button) this . findViewById( R . id . btnExit);
047        btnExit . setOnClickListener( new ClickEvent());
048//画板和画笔
049        sfv = ( SurfaceView) this . findViewById( R . id . SurfaceView01);
050        sfv . setOnTouchListener( new TouchEvent());
051        mPaint = new Paint();
052        mPaint . setColor( Color . GREEN); // 画笔为绿⾊
053        mPaint . setStrokeWidth( 1); // 设置画笔粗细
054//⽰波器类库
055        clsOscilloscope . initOscilloscope( xMax / 2 , yMax / 2 , sfv . getHeight ()/ 2);
056
057//缩放控件,X轴的数据缩⼩的⽐率⾼些
058        zctlX = ( ZoomControls) this . findViewById( R . id . zctlX);
059        zctlX . setOnZoomInClickListener( new View . OnClickListener() {
060            @Override
061public void onClick( View v) {
062if( clsOscilloscope . rateX > xMin)
063                    clsOscilloscope . rateX –;
064                setTitle( “X轴缩⼩” + String . valueOf( clsOscilloscope . rateX )+ “倍”
065                        + “,” + “Y轴缩⼩” + String . valueOf( clsOscilloscope . rateY )+ “倍”);
066            }
067        });
068        zctlX . setOnZoomOutClickListener( new View . OnClickListener() {
069            @Override
070public void onClick( View v) {
071if( clsOscilloscope . rateX < xMax)
072                    clsOscilloscope . rateX ++;
073                setTitle( “X轴缩⼩” + String . valueOf( clsOscilloscope . rateX )+ “倍”

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。