分析:连接按钮,开启MIC线程,开始记录MIC传递来的数据
if (flag_MIC) {
// 如果MIC标志位未true,则操作MIC
if (flag_MIC_conn) {
try {
// 停止MIC线程
MicroPhoneThread.pause();
flag_MIC_conn = false;
bt_connect.setText("连接");
//断开连接之后,让波形不再显示
//how?
mWaveform.ch_disappear();
} catch (Exception e) {
// TODO Auto-generated catch block
Toast.makeText(getBaseContext(), "MIC未断开", 1).show();
}
} else {
try {
// 开启MIC线程
MicroPhoneThread = new myMICThread();
MicroPhoneThread.start();
flag_MIC_conn = true;
mWaveform.ch_appear();
bt_connect.setText("断开");
} catch (Exception e) {
// TODO Auto-generated catch block
Toast.makeText(getBaseContext(), "MIC未连接", 1).show();
}
}
<span style="white-space:pre"> </span>MicroPhoneThread线程:
<span style="white-space:pre"> </span>public class myMICThread extends Thread {
<span style="white-space:pre"> </span>private AudioRecord ar;
<span style="white-space:pre"> </span>private int bs;
<span style="white-space:pre"> </span>private int SAMPLE_RATE_IN_HZ = 44100;
<span style="white-space:pre"> </span>private boolean isRun = false;
<span style="white-space:pre"> </span>public myMICThread() {
<span style="white-space:pre"> </span>super();
<span style="white-space:pre"> </span>// 一次从MIC中获取16位数据
<span style="white-space:pre"> </span>bs = AudioRecord.getMinBufferSize(SAMPLE_RATE_IN_HZ,
<span style="white-space:pre"> </span>AudioFormat.CHANNEL_CONFIGURATION_MONO,
<span style="white-space:pre"> </span>AudioFormat.ENCODING_PCM_16BIT);
<span style="white-space:pre"> </span>// 录音机实例化对象
<span style="white-space:pre"> </span>ar = new AudioRecord(MediaRecorder.AudioSource.MIC,
<span style="white-space:pre"> </span>SAMPLE_RATE_IN_HZ, AudioFormat.CHANNEL_CONFIGURATION_MONO,
<span style="white-space:pre"> </span>AudioFormat.ENCODING_PCM_16BIT, bs);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>public void run() {
<span style="white-space:pre"> </span>super.run();
<span style="white-space:pre"> </span>ar.startRecording();
<span style="white-space:pre"> </span>byte[] buffer = new byte[bs];
<span style="white-space:pre"> </span>isRun = true;
<span style="white-space:pre"> </span>while (isRun) {
<span style="white-space:pre"> </span>// 从ar中读取数据到buffer中,从第0位读到bs位
<span style="white-space:pre"> </span>int bytes = ar.read(buffer, 0, bs);
<span style="white-space:pre"> </span>// 将采集到的数据发送给主线程
<span style="white-space:pre"> </span>MicHandler.obtainMessage(osc.MESSAGE_READ, bytes, -1, buffer)
<span style="white-space:pre"> </span>.sendToTarget();
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>// 发送完毕数据信号之后,关闭资源
<span style="white-space:pre"> </span>ar.stop();
<span style="white-space:pre"> </span>ar.release();
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>// 对外提供一个停止线程的方法
<span style="white-space:pre"> </span>public void pause() {
<span style="white-space:pre"> </span>isRun = false;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>// 对外提供一个开启的方法
<span style="white-space:pre"> </span>public void start() {
<span style="white-space:pre"> </span>if (!isRun) {
<span style="white-space:pre"> </span>super.start();
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
一.读取数据的流程:
1.获取一个声音文件缓冲区
bs = AudioRecord.getMinBufferSize(SAMPLE_RATE_IN_HZ,<pre name="code" class="java"><span style="white-space:pre"> </span>AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT);
2.获取录音机实例化对象
ar = new AudioRecord(MediaRecorder.AudioSource.MIC,
SAMPLE_RATE_IN_HZ, AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT, bs);
<span style="white-space:pre"> </span>//MediaRecorder.AudioSource.MIC 声音源
<span style="white-space:pre"> </span>//SAMPLE_RATE_IN_HZ,采样频率
3.ar录音,每次录bs长度
ar.startRecording();
byte[] buffer = new byte[bs];
4.将录的数据读取到buffer数据中,并通过MicHandler发送给主线程,发送完毕后,释放资源
while (isRun) {
// 从ar中读取数据到buffer中,从第0位读到bs位
int bytes = ar.read(buffer, 0, bs);
// 将采集到的数据发送给主线程
MicHandler.obtainMessage(osc.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
}
// 发送完毕数据信号之后,关闭资源
ar.stop();
ar.release();
二.使用数据绘图
osc界面接收数据:
MicHandler = new Handler() {
int[] tempInt = new int[1000];
int counter = 0;
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
// int many = msg.arg1;
byte[] temp = (byte[]) msg.obj;
for (int i = 0; i < 700; i++) {
tempInt[i] = temp[i * MIC_level + 1];
}
//获取WaveFormView对象,
mWaveform.set_data(tempInt, tempInt);
}
};
set_data方法:
public void set_data(int[] data1, int[] data2)
bug出现在这个方法的第二行plot_thread.setRunning(false);
手动让绘图线程停止,这样的话,也就造成了第一次set_data之后,绘图线程不再执行。延伸:怎么画点的呢?
线程中
canvas=holder.lockCanvas(null);
synchronized(canvas){
//开始在canvas上画点
plot_area.plotPoints(canvas);
}
获取一个canvas,然后调用private WaveFormView plot_area;中的plotPoints方法进行绘图,该方法会使用到ch1和ch2的数据。相当于,没执行一次线程,canvas上的所有内容都是重新画一遍,不仅仅是波形,连边框,底纹,还有十字都是重新画的!