Android提高第十篇之AudioRecord实现"助听器"

Android可以通过MediaRecorder和AudioRecord这两个工具来实现录音,MediaRecorder直接把麦克风的数据存到文 件,并且能够直接进行编码(如AMR,MP3等),而AudioRecord则是读取麦克风的音频流。本文使用AudioRecord读取音频流,使用 AudioTrack播放音频流,通过“边读边播放”以及增大音量的方式来实现一个简单的助听器程序。

PS:由于目前的Android模拟器还不支持AudioRecord,因此本程序需要编译之后放到真机运行。

先贴出本文程序运行截图:

PS:程序音量调节只是程序内部调节音量而已,要调到最大音量还需要手动设置系统音量。

Android提高第十篇之AudioRecord实现"助听器"

使用AudioRecord必须要申请许可,在AndroidManifest.xml里面添加这句:

  1. < uses-permission   android:name = "android.permission.RECORD_AUDIO" > </ uses-permission >   

main.xml的源码如下:

  1. <? xml   version = "1.0"   encoding = "utf-8" ?>   
  2. < LinearLayout   xmlns:android = "http://schemas.android.com/apk/res/android"   
  3.     android:orientation = "vertical"   android:layout_width = "fill_parent"   
  4.     android:layout_height = "fill_parent" >   
  5.   
  6.     < Button   android:layout_height = "wrap_content"   android:id = "@+id/btnRecord"   
  7.         android:layout_width = "fill_parent"   android:text = "开始边录边放" > </ Button >   
  8.     < Button   android:layout_height = "wrap_content"   
  9.         android:layout_width = "fill_parent"   android:text = "停止"   android:id = "@+id/btnStop" > </ Button >   
  10.     < Button   android:layout_height = "wrap_content"   android:id = "@+id/btnExit"   
  11.         android:layout_width = "fill_parent"   android:text = "退出" > </ Button >   
  12.     < TextView   android:id = "@+id/TextView01"   android:layout_height = "wrap_content"   
  13.         android:text = "程序音量调节"   android:layout_width = "fill_parent" > </ TextView >   
  14.     < SeekBar   android:layout_height = "wrap_content"   android:id = "@+id/skbVolume"   
  15.         android:layout_width = "fill_parent" > </ SeekBar >   
  16.   
  17. </ LinearLayout >   

testRecord.java的源码如下:

  1. package  com.testRecord;  
  2.   
  3. import  android.app.Activity;  
  4. import  android.media.AudioFormat;  
  5. import  android.media.AudioManager;  
  6. import  android.media.AudioRecord;  
  7. import  android.media.AudioTrack;  
  8. import  android.media.MediaRecorder;  
  9. import  android.os.Bundle;  
  10. import  android.view.View;  
  11. import  android.widget.Button;  
  12. import  android.widget.SeekBar;  
  13. import  android.widget.Toast;  
  14.   
  15. public   class  testRecord  extends  Activity {  
  16.     /** Called when the activity is first created. */   
  17.     Button btnRecord, btnStop, btnExit;  
  18.     SeekBar skbVolume;//调节音量   
  19.     boolean  isRecording =  false ; //是否录放的标记   
  20.     static   final   int  frequency =  44100 ;  
  21.     static   final   int  channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;  
  22.     static   final   int  audioEncoding = AudioFormat.ENCODING_PCM_16BIT;  
  23.     int  recBufSize,playBufSize;  
  24.     AudioRecord audioRecord;  
  25.     AudioTrack audioTrack;  
  26.   
  27.     @Override   
  28.     public   void  onCreate(Bundle savedInstanceState) {  
  29.         super .onCreate(savedInstanceState);  
  30.         setContentView(R.layout.main);  
  31.         setTitle("助听器" );  
  32.         recBufSize = AudioRecord.getMinBufferSize(frequency,  
  33.                 channelConfiguration, audioEncoding);  
  34.   
  35.         playBufSize=AudioTrack.getMinBufferSize(frequency,  
  36.                 channelConfiguration, audioEncoding);  
  37.         // -----------------------------------------   
  38.         audioRecord = new  AudioRecord(MediaRecorder.AudioSource.MIC, frequency,  
  39.                 channelConfiguration, audioEncoding, recBufSize);  
  40.   
  41.         audioTrack = new  AudioTrack(AudioManager.STREAM_MUSIC, frequency,  
  42.                 channelConfiguration, audioEncoding,  
  43.                 playBufSize, AudioTrack.MODE_STREAM);  
  44.         //------------------------------------------   
  45.         btnRecord = (Button) this .findViewById(R.id.btnRecord);  
  46.         btnRecord.setOnClickListener(new  ClickEvent());  
  47.         btnStop = (Button) this .findViewById(R.id.btnStop);  
  48.         btnStop.setOnClickListener(new  ClickEvent());  
  49.         btnExit = (Button) this .findViewById(R.id.btnExit);  
  50.         btnExit.setOnClickListener(new  ClickEvent());  
  51.         skbVolume=(SeekBar)this .findViewById(R.id.skbVolume);  
  52.         skbVolume.setMax(100 ); //音量调节的极限   
  53.         skbVolume.setProgress(70 ); //设置seekbar的位置值   
  54.         audioTrack.setStereoVolume(0 .7f,  0 .7f); //设置当前音量大小   
  55.         skbVolume.setOnSeekBarChangeListener(new  SeekBar.OnSeekBarChangeListener() {  
  56.               
  57.             @Override   
  58.             public   void  onStopTrackingTouch(SeekBar seekBar) {  
  59.                 float  vol=( float )(seekBar.getProgress())/( float )(seekBar.getMax());  
  60.                 audioTrack.setStereoVolume(vol, vol);//设置音量   
  61.             }  
  62.               
  63.             @Override   
  64.             public   void  onStartTrackingTouch(SeekBar seekBar) {  
  65.                 // TODO Auto-generated method stub   
  66.             }  
  67.               
  68.             @Override   
  69.             public   void  onProgressChanged(SeekBar seekBar,  int  progress,  
  70.                     boolean  fromUser) {  
  71.                 // TODO Auto-generated method stub   
  72.             }  
  73.         });  
  74.     }  
  75.   
  76.     @Override   
  77.     protected   void  onDestroy() {  
  78.         super .onDestroy();  
  79.         android.os.Process.killProcess(android.os.Process.myPid());  
  80.     }  
  81.   
  82.     class  ClickEvent  implements  View.OnClickListener {  
  83.   
  84.         @Override   
  85.         public   void  onClick(View v) {  
  86.             if  (v == btnRecord) {  
  87.                 isRecording = true ;  
  88.                 new  RecordPlayThread().start(); // 开一条线程边录边放   
  89.             } else   if  (v == btnStop) {  
  90.                 isRecording = false ;  
  91.             } else   if  (v == btnExit) {  
  92.                 isRecording = false ;  
  93.                 testRecord.this .finish();  
  94.             }  
  95.         }  
  96.     }  
  97.   
  98.     class  RecordPlayThread  extends  Thread {  
  99.         public   void  run() {  
  100.             try  {  
  101.                 byte [] buffer =  new   byte [recBufSize];  
  102.                 audioRecord.startRecording();//开始录制   
  103.                 audioTrack.play();//开始播放   
  104.                   
  105.                 while  (isRecording) {  
  106.                     //从MIC保存数据到缓冲区   
  107.                     int  bufferReadResult = audioRecord.read(buffer,  0 ,  
  108.                             recBufSize);  
  109.   
  110.                     byte [] tmpBuf =  new   byte [bufferReadResult];  
  111.                     System.arraycopy(buffer, 0 , tmpBuf,  0 , bufferReadResult);  
  112.                     //写入数据即播放   
  113.                     audioTrack.write(tmpBuf, 0 , tmpBuf.length);  
  114.                 }  
  115.                 audioTrack.stop();  
  116.                 audioRecord.stop();  
  117.             } catch  (Throwable t) {  
  118.                 Toast.makeText(testRecord.this , t.getMessage(),  1000 );  
  119.             }  
  120.         }  
  121.     };  

你可能感兴趣的:(thread,xml,android,OS)