zoukankan      html  css  js  c++  java
  • 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音频采集(捕获)

    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播放器   使用方法 : 文件->导入->裸数据   然后根据你录音时的配置填写相应参数 就可以播放了!

  • 相关阅读:
    Filter过滤器
    jsp-JSTL表达式
    jsp-EL表达式
    JSP概述
    servlet编码问题
    微信开放平台-踩坑1
    Supervisor的安装以及使用
    laravel-mix的安装
    Laravel框架中打印sql
    Laravel 5.7 使用 PHP artisan migrate 的问题
  • 原文地址:https://www.cnblogs.com/stnlcd/p/7151413.html
Copyright © 2011-2022 走看看