通过J2ME的录音功能实现简易示波器
扫描二维码
随时随地手机看文章
早就有人通过PC声卡的输入(麦克风孔)来做模拟示波器,但是用手机来实现的比较少。用J2ME的MMAPI实现模拟示波器,具体效果稍逊于智能机,因为智能机可以实时读取麦克风输入流,而J2ME还需要有短暂的缓冲构成了阻塞,不过,实现出来玩一下还是足够了。
先贴出效果图:
左图是程序在WTK运行的结果,右图是Audition读取音频输入口的波形,信号源是一个经过信号放大的压力传感器。
程序使用NetBeans + LWUIT类库,接下来贴出全部代码:
importcom.sun.lwuit.Command;
importcom.sun.lwuit.Display;
importcom.sun.lwuit.Form;
importcom.sun.lwuit.events.ActionEvent;
importcom.sun.lwuit.events.ActionListener;
importcom.sun.lwuit.layouts.BorderLayout;
importjava.io.ByteArrayOutputStream;
importjavax.microedition.media.Manager;
importjavax.microedition.media.Player;
importjavax.microedition.media.control.RecordControl;
/**
*@author张国威
*/
publicclassFrm_MainMenuextendsjavax.microedition.midlet.MIDletimplementsActionListener{
publicFormform;
privateCommandcmdExit=newCommand("退出",1);
privateThreadReceivethreadReceive=newThreadReceive();//接收数据线程
privateCmp_Wavecmp_HeartWave=null;
privatePlayercapturePlayer=null;
privateRecordControlrecordControl=null;
privateByteArrayOutputStreambos=newByteArrayOutputStream();
publicvoidstartApp(){
Display.init(this);
form=newForm();//达到全屏的效果
cmp_HeartWave=newCmp_Wave(form.getHeight(),form.getWidth());
form.getStyle().setBgImage(null);//本窗体不需要背景
form.addCommand(cmdExit);
form.setCommandListener(this);
form.setLayout(newBorderLayout());
//设置画板控件
form.addComponent(BorderLayout.CENTER,cmp_HeartWave);//添加控件
form.show();
try{
capturePlayer=Manager.createPlayer("capture://audio?rate=8000&bits=8&channels=1");//PCM,8位,8kH
if(capturePlayer!=null){
capturePlayer.realize();
recordControl=(RecordControl)capturePlayer
.getControl("javax.microedition.media.control.RecordControl");
if(recordControl==null)
thrownewException("NoRecordControlavailable");
recordControl.setRecordStream(bos);
}else{
thrownewException("CaptureAudioPlayerisnotavailable");
}
}catch(Exceptione){}
threadReceive.start();//开始启动线程
}
/*
*byte转为int的函数,因为JAVA的byte范围从-127~127
*/
publicstaticintunsignedByteToInt(byteb){
return(int)b&0xFF;
}
classThreadReceiveextendsThread{
privatebooleanisRuning=true;//默认线程内部while循环可以执行
publicvoidStopThread()
{
isRuning=false;
}
publicvoidrun(){
//*************************************************************
//绘制波形数据
//*************************************************************
try{
capturePlayer.start();
while(isRuning)
{
recordControl=(RecordControl)capturePlayer.getControl("javax.microedition.media.control.RecordControl");
recordControl.setRecordStream(bos);
recordControl.startRecord();
Thread.sleep(25);//停顿25ms录音
recordControl.stopRecord();
recordControl.commit();
//由于采集频率太高,手机不能完全显示,所以需要通过均值滤波来降低分辨率
intZoom_out=200;//缩小200倍
int[]bits=newint[bos.toByteArray().length/Zoom_out];
for(inti=0,total=0,index=0;i
{
total=total+unsignedByteToInt(bos.toByteArray()[i]);
if(i%Zoom_out==0&&i!=0)
{
bits[index]=total/Zoom_out;
total=0;
index++;
}
}
cmp_HeartWave.UpdateVerticalWave(bits);