通过J2ME的录音功能实现简易示波器

 

本文来自http://blog.csdn.net/hellogv/ ,引用必须注明出处!      

       早就有人通过PC声卡的输入(麦克风孔)来做模拟示波器,但是用手机来实现的比较少。用J2ME的MMAPI实现模拟示波器,具体效果稍逊于智能机,因为智能机可以实时读取麦克风输入流,而J2ME还需要有短暂的缓冲构成了阻塞,不过,实现出来玩一下还是足够了。

先贴出效果图:

左图是程序在WTK运行的结果,右图是Audition读取音频输入口的波形,信号源是一个经过信号放大的压力传感器。

程序使用NetBeans + LWUIT类库,接下来贴出全部代码:

  1. import com.sun.lwuit.Command;  
  2. import com.sun.lwuit.Display;  
  3. import com.sun.lwuit.Form;  
  4. import com.sun.lwuit.events.ActionEvent;  
  5. import com.sun.lwuit.events.ActionListener;  
  6. import com.sun.lwuit.layouts.BorderLayout;  
  7. import java.io.ByteArrayOutputStream;  
  8. import javax.microedition.media.Manager;  
  9. import javax.microedition.media.Player;  
  10. import javax.microedition.media.control.RecordControl;  
  11.   
  12. /** 
  13.  * @author 张国威 
  14.  */  
  15. public class Frm_MainMenu extends javax.microedition.midlet.MIDlet implements ActionListener {  
  16.     public Form form ;  
  17.     private  Command cmdExit = new Command("退出"1);  
  18.     private ThreadReceive threadReceive =new ThreadReceive();//接收数据线程   
  19.     private Cmp_Wave cmp_HeartWave=null;  
  20.     private Player capturePlayer = null;  
  21.     private RecordControl recordControl = null;  
  22.     private ByteArrayOutputStream bos = new ByteArrayOutputStream();  
  23.     public void startApp() {  
  24.         Display.init(this);  
  25.           
  26.         form = new Form();//达到全屏的效果   
  27.         cmp_HeartWave=new Cmp_Wave(form.getHeight(),form.getWidth());  
  28.         form.getStyle().setBgImage(null);//本窗体不需要背景   
  29.         form.addCommand(cmdExit);  
  30.         form.setCommandListener(this);  
  31.         form.setLayout(new BorderLayout());  
  32.         //设置画板控件   
  33.         form.addComponent(BorderLayout.CENTER,cmp_HeartWave);//添加控件   
  34.         form.show();  
  35.         try {  
  36.           capturePlayer = Manager.createPlayer("capture://audio?rate=8000&bits=8&channels=1");//PCM,8位,8kH  
  37.           if (capturePlayer != null) {  
  38.             capturePlayer.realize();  
  39.             recordControl = (RecordControl) capturePlayer  
  40.                 .getControl("javax.microedition.media.control.RecordControl");  
  41.             if (recordControl == null)  
  42.               throw new Exception("No RecordControl available");  
  43.             recordControl.setRecordStream(bos);  
  44.           } else {  
  45.             throw new Exception("Capture Audio Player is not available");  
  46.           }  
  47.         } catch (Exception e) {}  
  48.         threadReceive.start();//开始启动线程   
  49.   }  
  50. /* 
  51.  * byte转为int的函数,因为JAVA的byte范围从-127~127 
  52.  */  
  53. public static int unsignedByteToInt(byte b) {  
  54.     return (int) b & 0xFF;  
  55.     }  
  56. class ThreadReceive extends Thread {  
  57.       private boolean isRuning=true;//默认线程内部while循环可以执行   
  58.       public void StopThread()  
  59.       {  
  60.           isRuning=false;  
  61.       }  
  62.       public void run(){  
  63.           //*************************************************************   
  64.           //绘制波形数据   
  65.           //*************************************************************   
  66.           try {  
  67.               capturePlayer.start();  
  68.               while(isRuning)  
  69.               {  
  70.                   recordControl = (RecordControl) capturePlayer.getControl("javax.microedition.media.control.RecordControl");  
  71.                   recordControl.setRecordStream(bos);  
  72.                   recordControl.startRecord();  
  73.                   Thread.sleep(25);//停顿25ms录音   
  74.                   recordControl.stopRecord();  
  75.                   recordControl.commit();  
  76.                   //由于采集频率太高,手机不能完全显示,所以需要通过均值滤波来降低分辨率   
  77.                   int Zoom_out=200;//缩小200倍   
  78.                   int[] bits=new int[bos.toByteArray().length/Zoom_out];  
  79.                   for(int i=0,total=0,index=0;i<bos.toByteArray().length;i++)  
  80.                   {  
  81.                       total=total+unsignedByteToInt(bos.toByteArray()[i]);  
  82.                       if(i%Zoom_out==0 && i!=0)  
  83.                       {  
  84.                           bits[index]=total/Zoom_out;  
  85.                           total=0;  
  86.                           index++;  
  87.                       }  
  88.                   }  
  89.                   cmp_HeartWave.UpdateVerticalWave(bits);  
  90.                   bos.reset();  
  91.               }  
  92.               capturePlayer.stop();  
  93.               capturePlayer.close();  
  94.           } catch (Exception e) {}  
  95.       }  
  96.   }  
  97.     public void actionPerformed(ActionEvent arg0) {  
  98.         Command command=arg0.getCommand();  
  99.         if(command==cmdExit)//退出程序   
  100.             notifyDestroyed();  
  101.     }  
  102.     protected void pauseApp() {}  
  103.     protected void destroyApp(boolean arg0) {}  
  104.   
  105. }  

 

以下代码为画波形图的代码:

  1. /* 
  2.  * To change this template, choose Tools | Templates 
  3.  * and open the template in the editor. 
  4.  */  
  5. import com.sun.lwuit.Component;  
  6. import com.sun.lwuit.Container;  
  7. import com.sun.lwuit.Graphics;  
  8. import com.sun.lwuit.Image;  
  9. import com.sun.lwuit.layouts.BorderLayout;  
  10. /** 
  11.  * 
  12.  * @author Administrator 
  13.  */  
  14. public class Cmp_Wave extends Container{  
  15.    private Image imgWaveCanvas;//波形图画板,图形画在图像上,再不断地贴图到屏幕   
  16.    private int height; //自己定义的画板高度 getHeight()   
  17.    private int width; //自己定义的画板宽度 getWidth()   
  18.    private int old_xPos=-1;//位置初始化   
  19.    private int old_yPos=-1;//位置初始化   
  20.    private Component cmpWaveCanvas;//显示波形控件   
  21.    private int[] point=null;//每次收到的point数组   
  22.    public Cmp_Wave(int canvasHeight,int canvasWidth)  
  23.    {  
  24.        super.setLayout(new BorderLayout());  
  25.        super.addComponent(BorderLayout.CENTER,WaveCanvas(canvasHeight,canvasWidth));//波形显示在中间   
  26.    }  
  27.    private Component WaveCanvas(int canvasHeight,int canvasWidth)  
  28.   {  
  29.       height=canvasHeight;  
  30.       width=canvasWidth;  
  31.       //-------初始化波形画板图像   
  32.       imgWaveCanvas=Image.createImage(width, height);  
  33.       //-------初始化波形画板控件,在控件上绘制波形画板图像   
  34.       cmpWaveCanvas=new Component(){  
  35.             public void paint(Graphics g) {  
  36.                 //在内存中绘制波形图   
  37.                 Graphics canvas=imgWaveCanvas.getGraphics();  
  38.                   
  39.                 if(point==null)//如果point还没初始化   
  40.                     return;//不执行下面语句   
  41.                 for(int i=0;i<point.length;i++)  
  42.                 {  
  43.                     if(old_xPos>=width //如果xPos超过屏幕宽度   
  44.                     || old_xPos==-1//如果PaintVerticalWave是第一次运行   
  45.                     {  
  46.                         old_xPos=0;//归零画图   
  47.                         old_yPos=height/2;//中心点画图   
  48.                         canvas.setColor(0x444444);//设置背景色   
  49.                         canvas.fillRect(00, width, height);  
  50.                     }  
  51.                     int new_yPosPoint=point[i] ;  
  52.                     canvas.setColor(0xCCCCCC);//线条色   
  53.                     canvas.drawLine(old_xPos,old_yPos,old_xPos+1,new_yPosPoint);  
  54.                     old_xPos++;  
  55.                     old_yPos=new_yPosPoint;  
  56.                 }  
  57.                 //把内存中的波形图画到控件上   
  58.                 g.drawImage(imgWaveCanvas, 00);  
  59.             }  
  60.       };        
  61.       cmpWaveCanvas.setFocusPainted(false);  
  62.       cmpWaveCanvas.setFocusable(false);  
  63.       return cmpWaveCanvas;  
  64.   }  
  65.    public void UpdateVerticalWave(int []yPos) {  
  66.        //更新绘图数组   
  67.        int []tmpPos=new int[yPos.length];//临时数组,只取原数组的waveN分之一   
  68.        for(int i=0,ii=0;i<tmpPos.length;i++,ii+=1)  
  69.            tmpPos[i]=yPos[ii];  
  70.        point=tmpPos;  
  71.        //重新绘图   
  72.        cmpWaveCanvas.repaint();  
  73.    }  
  74. }  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值