Android 音频采集——MediaRecord(编码后录影文件) AudioRecord(PCM原始数据)

学向勤中得,萤窗万卷书。这篇文章主要讲述Android 音频采集——MediaRecord(编码后录影文件) AudioRecord(PCM原始数据)相关的知识,希望能为你提供帮助。
http://blog.csdn.net/java_android_c/article/details/52619737
Android  音频简介
常见的音频编解码的类型:AAC   OPUS  MP3   AMR   Ogg   PCM  
AAC: 高级音频编码   对应   .m4a(audio/m4a)或者.3pg(audio/3gpp)文件   HEAAC:高级AAC,使用的比较多。
OPUS:有损声音编码的格式,由互联网工程任务组(IETF)进来开发,适用于网络上的实时声音传输,如:语音通话
MP3: 使用的最广泛的音频编解码器   对应 .mp3(audio/mp3) 各种音乐网站一般用这种。
AMR:自适应多速率音频编解码器,一般用于语音呼叫程序。
Ogg:开发的无专利的音频编解码器,其质量可与商业的和手专利保护的MP3以及AAC编解码相媲美。
PCM :原始音频,在android平台上由audio record直接录用下来的,未经过编码的。
视频直播,语音通话中一般使用AAC或者OPUS ,如果对声音要进行处理就需要使用PCM原始音频加工处理,然后再进行编码.
【Android 音频采集——MediaRecord(编码后录影文件) AudioRecord(PCM原始数据)】 
Android音频采集(捕获)
android平台上的音频采集一般就三种:1.利用android内置的应用程序   2.使用MediaRecorder进行音频捕获   3.使用AudioRecord进行音频捕获。此3种方式的灵活性逐渐增大,相应的所需要做的工作也逐渐增多。
一、Android 内置的应用程序。
[java]  view plain  copy  

  1. Intent  intent=new  Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);    
  2. startActivityForResult(intent,0);   //通过startActivityForResult获取音频录制的结果的路径   
这种方式灵活度最差,一般就是做着演示下,开发中基本不用这种方案。
 
二、使用MediaRecorder进行音频的捕获。   这个是 录影视频和音频分别编码后保存成一个文件,单独音频也可以,不过是编码后的数据
这种方案相较于调用系统内置的用用程序,灵活度要高很多,便于开发者在UI界面上布局,而且系统封装的很好,便于使用,唯一的缺点是使用它录下来的音频是经过编码的,没有办法的得到原始的音频。同时MediaRecorder即可用于音频的捕获也可以用于视频的捕获相当的强大。实际开发中没有特殊需求的话,用的是比较多的!
使用步骤:
创建MediaRecorder对象,调用如下方法(Ps:调用顺序顺序对结果的影响是非常的大。)
MediaRecorder recorder=new MediaRecorder(); //创建MediaRecoder对象
1.recorder.setAudiosource(MediaRecorder.AudioSource.MIC); //调用setAudioSource方法 (调用的第一个方法) 
    MediaRecorder.AudioSource.CAMCORDER和MediaRecorder.AudioSource.VOICE_RECOGNITION当设备具有。> =2个麦克风的时候就可以使用它们。
    MediaRecorder.AudioSource.VOICE_CALL从电话中录音
2.recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); //setOutputFormat方法(调用的第二个方法)
    MediaRecorder.OutputFormat.THREE_GPP 输出文件将是一个扩展名为(.3gp)的文件。它可能包含音频和视频。
    MediaRecorder.OutputFormat.MPEG_4 输出一个MPEG_4文件,它可能包含音频和视频。
3.recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); //setAudioEncoder方法 (这是调用的第三个方法)
4.recorder.setOutputFile(url); //setOutputFile方法 url是目标文件路径(这是调用的第四个方法)
以上四个方法一次调用完成之后,就可以像MediaPlayer一样控制录制和暂停录制了。
 
[html]  view plain  copy  
  1. < ?xml  version="1.0"  encoding="utf-8"?>    
  2. < LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"   
  3.         android:orientation="vertical"   
  4.         android:layout_width="fill_parent"   
  5.         android:layout_height="fill_parent"   
  6.         android:background="#fff"   
  7.         android:gravity="center">    
  8.    
  9.         < Button     
  10.                 android:text="开始录音"     
  11.                 android:id="@+id/StartRecording"     
  12.                 android:layout_width="wrap_content"     
  13.                 android:layout_height="wrap_content"/>    
  14.          
  15.         < Button     
  16.                 android:text="停止录音"     
  17.                 android:id="@+id/StopRecording"     
  18.                 android:layout_width="wrap_content"     
  19.                 android:layout_height="wrap_content"/>    
  20.            
  21. < /LinearLayout>    
 
[java]  view plain  copy  
  1. public  class  MainActivity  extends  Activity  implements  OnClickListener{   
  2.          
  3.         Button  startRecording,  stopRecording; //开始录音、停止录音、释放资源   
  4.         MediaRecorder  recorder;    
  5.         File  audioFile;   //录音保存的文件   
  6.         boolean  isRecoding=false; //  true  表示正在录音   
  7.    
  8.         @Override   
  9.         public  void  onCreate(Bundle  savedInstanceState)  {   
  10.                 super.onCreate(savedInstanceState);    
  11.                 requestWindowFeature(Window.FEATURE_NO_TITLE);    
  12.                 setContentView(R.layout.main);    
  13.                 init();    
  14.                 initListener();    
  15.         }   
  16.            
  17.         //初始化   
  18.         public  void  init(){   
  19.                 stopRecording  =  (Button)  this.findViewById(R.id.StopRecording);    
  20.                 startRecording  =  (Button)  this.findViewById(R.id.StartRecording);    
  21.                    
  22.                 recorder  =  new  MediaRecorder();    
  23.                 recorder.setAudioSource(MediaRecorder.AudioSource.MIC); //设置播放源  麦克风   
  24.                 recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);   //设置输入格式  3gp   
  25.                 recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);   //设置编码  AMR   
  26.         }   
  27.            
  28.         //设置监听器   
  29.         public  void  initListener(){   
  30.                 startRecording.setOnClickListener(this);    
  31.                 stopRecording.setOnClickListener(this);    
  32.         }   
  33.                  
  34.         //录音           
  35.         public  void  recod(){           
  36.                            
  37.                         //此处还应该对手机进行下判断,判断下手机里面有没有内存卡   
  38.                         //保存在SD卡下MediaRecorderTest文件夹中   
  39.                         File  path  =  new  File(Environment.getExternalStorageDirectory().getAbsolutePath()+  "/MediaRecorderTest");      
  40.                         if(!path.exists())   
  41.                         {   
  42.                                 path.mkdirs();    
  43.                         }   
  44.                            
  45.                         try  {   
  46.                                 audioFile=new  File(path,"test.3gp");    
  47.                                 if(audioFile.exists())   
  48.                                 {   
  49.                                         audioFile.delete();    
  50.                                 }   
  51.                                 audioFile.createNewFile(); //创建文件   
  52.                                    
  53.                               }  catch  (Exception  e)  {   
  54.                                 throw  new  RuntimeException("Couldn‘t  create  recording  audio  file",  e);    
  55.                         }   
  56.    
  57.                         recorder.setOutputFile(audioFile.getAbsolutePath());   //设置输出文件   
  58.    
  59.                         try  {   
  60.                                 recorder.prepare();    
  61.                         }  catch  (IllegalStateException  e)  {   
  62.                                 throw  new  RuntimeException("IllegalStateException  on  MediaRecorder.prepare",  e);    
  63.                         }  catch  (IOException  e)  {   
  64.                                 throw  new  RuntimeException("IOException  on  MediaRecorder.prepare",  e);    
  65.                         }   
  66.                         isRecoding=true;    
  67.                         recorder.start();    
  68.         }   
  69.            
  70.            
  71.         public  void  onClick(View  v)  {   
  72.                    
  73.                 switch  (v.getId())   
  74.                 {         
  75.                         //开始录音   
  76.                         case  R.id.StartRecording:   
  77.                         {       
  78.                                 Toast.makeText(MainActivity.this,"开始录音",Toast.LENGTH_SHORT).show();    
  79.                                 recod();    
  80.                                 break;    
  81.                         }   
  82.                            
  83.                         //停止录音   
  84.                         case  R.id.StopRecording:   
  85.                         {         
  86.                                 if(isRecoding)   
  87.                                 {   
  88.                                   Toast.makeText(MainActivity.this,"停止录音",Toast.LENGTH_SHORT).show();    
  89.                                   recorder.stop();    
  90.                                   recorder.release();    
  91.                                 }   
  92.                                 break;    
  93.                         }   
  94.                            
  95.                       default:   
  96.                             break;    
  97.                 }   
  98.         }   
  99.            
  100. }   
[java]  view plain  copy  
  1. MediaRecoder的其他API方法:   
  2. //设置录制允许的最大时长  单位是毫秒。必须在setOutFormat方法之后,prepare方法之前使用。   
  3. setMaxDuration(int);    
  4. //设置文件录制的存放文件的最大值,单位是字节  。必须在setOutFormat方法之后,prepare方法之前使用。     
  5. setMaxFileSize(long)   
  6. //允许录制的音频通道数,通常是一个通道(单声道,2个通道双声道,立体声)。必须在调用prepare方法之前调用。   
  7. setAudioChannels(int)   
  8. //允许制定捕获和编码音频的采样率。硬件和使用的编码器将会决定合适的采样率。必须在调用prepare方法之前调用。   
  9. setAudioSamplingRate(int)   
  10. //允许指定当压缩音频时编码器所使用的每秒位数(位/秒)。必须在调用prepare方法之前调用。   
  11. setAudioEncodingBitRate在(int)   
 
 
三、使用AudioRecord 进行音频捕获。——从某个输入,直接捕获音频数据:PCM格式
这种方法是3种之中最为灵活的,能让开发者最大限度的处理采集的音频,同时它捕获到的音频是原始音频PCM格式的!像做变声处理的需要就必须要用它收集音频。在实际开发中,它也是最常用来采集音频的手段。也是本文介绍的重点。
 
[java]  view plain  copy  
  1. //指定音频源  这个和MediaRecorder是相同的     
  2. int  audioSource=MediaRecorder.AudioSource.MIC;    
  3. //指定采样率  (MediaRecoder  的采样率通常是8000Hz  CD的通常是44100Hz  不同的Android手机硬件将能够以不同的采样率进行采样。其中11025是一个常见的采样率)   
  4. int  sampleRateInHz=11025  ;    
  5. //指定捕获音频的通道数目。在AudioFormat类中指定用于此的常量       
  6. int  channelConfig=AudioFormat.CHANNEL_CONFIGURATION_MONO;    
  7. //指定音频量化位数  ,在AudioFormaat类中指定了以下各种可能的常量。通常我们选择ENCODING_PCM_16BIT和ENCODING_PCM_8BIT  PCM代表的是脉冲编码调制,它实际上是原始音频样本。   
  8. //因此可以设置每个样本的分辨率为16位或者8位,16位将占用更多的空间和处理能力,表示的音频也更加接近真实。   
  9. int  audioFormat=AudioFormat.ENCODING_PCM_16BIT;    
  10. 指定缓冲区大小。调用AudioRecord类的getMinBufferSize方法可以获得。   
  11. //创建AudioRecord。AudioRecord类实际上不会保存捕获的音频,因此需要手动创建文件并保存下载。   
  12. AudioRecord  record=new  AudioRecord(audioSource,sampleRateInHz,channelConfig,audioFormat,bufferSizeInBytes);      
 
布局xml文件和MediaRecorder Demo中一样,2个按钮而已!就不贴了,下面贴出AudioRecord的Demo的源代码.
 
[java]  view plain  copy  
  1. public  class  MainActivity  extends  Activity  implements  OnClickListener  {   
  2.         Button  startRecordingButton,  stopRecordingButton; //开始录音、停止录音   
  3.         File  recordingFile; //储存AudioRecord录下来的文件   
  4.         boolean  isRecording  =  false;   //true表示正在录音   
  5.         AudioRecord  audioRecord=null;    
  6.         File  parent=null; //文件目录   
  7.         int  bufferSize=0; //最小缓冲区大小   
  8.         int  sampleRateInHz  =  11025; //采样率   
  9.         int  channelConfig  =  AudioFormat.CHANNEL_CONFIGURATION_MONO;   //单声道   
  10.         int  audioFormat  =  AudioFormat.ENCODING_PCM_16BIT;   //量化位数   
  11.         String  TAG="AudioRecord";    
  12.    
  13.         @Override   
  14.         public  void  onCreate(Bundle  savedInstanceState)  {   
  15.                 super.onCreate(savedInstanceState);    
  16.                 requestWindowFeature(Window.FEATURE_NO_TITLE);    
  17.                 setContentView(R.layout.main);    
  18.                 init();    
  19.                 initListener();    
  20.         }   
  21.            
  22.         //初始化   
  23.         public  void  init(){   
  24.                 startRecordingButton  =  (Button)findViewById(R.id.StartRecordingButton);    
  25.                 stopRecordingButton  =  (Button)findViewById(R.id.StopRecordingButton);    
  26.                    
  27.                 bufferSize  =  AudioRecord.getMinBufferSize(sampleRateInHz,channelConfig,  audioFormat); //计算最小缓冲区   
  28.                 audioRecord  =  new  AudioRecord(MediaRecorder.AudioSource.MIC,sampleRateInHz,channelConfig,  audioFormat,  bufferSize); //创建AudioRecorder对象   
  29.                    
  30.                 parent  =  new  File(Environment.getExternalStorageDirectory().getAbsolutePath()+  "/AudiioRecordTest");    
  31.                 if(!parent.exists())   
  32.                         parent.mkdirs(); //创建文件夹   
  33.         }   
  34.            
  35.         //初始化监听器   
  36.         public  void  initListener(){   
  37.                 startRecordingButton.setOnClickListener(this);    
  38.                 stopRecordingButton.setOnClickListener(this);    
  39.         }   
  40.            
  41.         public  void  onClick(View  v)  {   
  42.                 switch  (v.getId())  {   
  43.                 //开始录音   
  44.                 case  R.id.StartRecordingButton:   
  45.                 {   
  46.                         record();    
  47.                         break;    
  48.                 }   
  49.                    
  50.                 //停止录音   
  51.                 case  R.id.StopRecordingButton:   
  52.                 {   
  53.                         stopRecording();    
  54.                         break;    
  55.                 }   
  56.         }   
  57.                    
  58.   }   
  59.    
  60.         //开始录音   
  61.         public  void  record()  {   
  62.                 isRecording  =  true;    
  63.                 new  Thread(new  Runnable()  {   
  64.                         @Override   
  65.                         public  void  run()  {   
  66.                                 isRecording  =  true;    
  67.                                    
  68.                                 recordingFile  =  new  File(parent,"audiotest.pcm");    
  69.                                 if(recordingFile.exists()){   
  70.                                         recordingFile.delete();    
  71.                                 }   
  72.                                    
  73.                                 try  {   
  74.                                           recordingFile.createNewFile();    
  75.                                         }     
  76.                                 catch  (IOException  e)  {   
  77.                                           e.printStackTrace();    
  78.                                           Log.e(TAG,"创建储存音频文件出错");    
  79.                                         }   
  80.                                    
  81.                                    
  82.                                 try  {   
  83.                                 DataOutputStream  dos  =  new  DataOutputStream(new  BufferedOutputStream(new  FileOutputStream(recordingFile)));    
  84.                                 byte[]  buffer  =  new  byte[bufferSize];    
  85.                                 audioRecord.startRecording(); //开始录音   
  86.                                         int  r  =  0;    
  87.                                         while  (isRecording)  {   
  88.                                                 int  bufferReadResult  =  audioRecord.read(buffer,0,bufferSize);    
  89.                                                 for  (int  i  =  0;   i  <   bufferReadResult;   i++)     
  90.                                                 {   
  91.                                                         dos.write(buffer[i]);      
  92.                                                 }   
  93.                                                 r++;    
  94.                                         }   
  95.                                         audioRecord.stop(); //停止录音   
  96.                                         dos.close();    
  97.                                 }  catch  (Throwable  t)  {   
  98.                                         Log.e(TAG,  "Recording  Failed");    
  99.                                 }   
  100.                                    
  101.                         }   
  102.                 }).start();    
  103.    
  104.         }   
  105.            
  106.         //停止录音   
  107.         public  void  stopRecording()     
  108.         {   
  109.                 isRecording  =  false;    
  110.         }   
  111.    
  112.            
  113. }   
 
注意这几个Demo都要添加以下权限:
[html]  view plain  copy  
  1. < uses-permission  android:name="android.permission.RECORD_AUDIO"/>    
  2. < uses-permission  android:name="android.permission.WRITE_EXTERNAL_STORAGE"  />    
四、备注:
MediaRecorder采集音频的Demo源码
AudioRecord采集音频的Demo源码
原始音频PCM播放器    使用方法 : 文件-> 导入-> 裸数据   然后根据你录音时的配置填写相应参数 就可以播放了!
 







    推荐阅读