【Android】示波器MIC模式下波形只显示一次就固定

本文探讨了在Android中使用MIC模式时,示波器波形只显示一次的问题。通过分析连接按钮功能和启动录音线程,详细介绍了如何获取声音文件缓冲区和录音机实例。同时,文章还触及了示波器界面如何接收并显示数据,以及如何在线程中进行点的绘制,为解决波形固定不动的难题提供了思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

分析:连接按钮,开启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上的所有内容都是重新画一遍,不仅仅是波形,连边框,底纹,还有十字都是重新画的!



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值