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 內置的應用程序。
- Intent intent=new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
- 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一樣控制錄制和暫停錄制了。
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:background="#fff"
- android:gravity="center">
- <Button
- android:text="開始錄音"
- android:id="@+id/StartRecording"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
- <Button
- android:text="停止錄音"
- android:id="@+id/StopRecording"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
- </LinearLayout>
- public class MainActivity extends Activity implements OnClickListener{
- Button startRecording, stopRecording;//開始錄音、停止錄音、釋放資源
- MediaRecorder recorder;
- File audioFile; //錄音保存的文件
- boolean isRecoding=false;// true 表示正在錄音
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- setContentView(R.layout.main);
- init();
- initListener();
- }
- //初始化
- public void init(){
- stopRecording = (Button) this.findViewById(R.id.StopRecording);
- startRecording = (Button) this.findViewById(R.id.StartRecording);
- recorder = new MediaRecorder();
- recorder.setAudioSource(MediaRecorder.AudioSource.MIC);//設置播放源 麥克風
- recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); //設置輸入格式 3gp
- recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); //設置編碼 AMR
- }
- //設置監聽器
- public void initListener(){
- startRecording.setOnClickListener(this);
- stopRecording.setOnClickListener(this);
- }
- //錄音
- public void recod(){
- //此處還應該對手機進行下判斷,判斷下手機里面有沒有內存卡
- //保存在SD卡下MediaRecorderTest文件夾中
- File path = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+ "/MediaRecorderTest");
- if(!path.exists())
- {
- path.mkdirs();
- }
- try {
- audioFile=new File(path,"test.3gp");
- if(audioFile.exists())
- {
- audioFile.delete();
- }
- audioFile.createNewFile();//創建文件
- } catch (Exception e) {
- throw new RuntimeException("Couldn't create recording audio file", e);
- }
- recorder.setOutputFile(audioFile.getAbsolutePath()); //設置輸出文件
- try {
- recorder.prepare();
- } catch (IllegalStateException e) {
- throw new RuntimeException("IllegalStateException on MediaRecorder.prepare", e);
- } catch (IOException e) {
- throw new RuntimeException("IOException on MediaRecorder.prepare", e);
- }
- isRecoding=true;
- recorder.start();
- }
- public void onClick(View v) {
- switch (v.getId())
- {
- //開始錄音
- case R.id.StartRecording:
- {
- Toast.makeText(MainActivity.this,"開始錄音",Toast.LENGTH_SHORT).show();
- recod();
- break;
- }
- //停止錄音
- case R.id.StopRecording:
- {
- if(isRecoding)
- {
- Toast.makeText(MainActivity.this,"停止錄音",Toast.LENGTH_SHORT).show();
- recorder.stop();
- recorder.release();
- }
- break;
- }
- default:
- break;
- }
- }
- }
- MediaRecoder的其他API方法:
- //設置錄制允許的最大時長 單位是毫秒。必須在setOutFormat方法之后,prepare方法之前使用。
- setMaxDuration(int);
- //設置文件錄制的存放文件的最大值,單位是字節 。必須在setOutFormat方法之后,prepare方法之前使用。
- setMaxFileSize(long)
- //允許錄制的音頻通道數,通常是一個通道(單聲道,2個通道雙聲道,立體聲)。必須在調用prepare方法之前調用。
- setAudioChannels(int)
- //允許制定捕獲和編碼音頻的采樣率。硬件和使用的編碼器將會決定合適的采樣率。必須在調用prepare方法之前調用。
- setAudioSamplingRate(int)
- //允許指定當壓縮音頻時編碼器所使用的每秒位數(位/秒)。必須在調用prepare方法之前調用。
- setAudioEncodingBitRate在(int)
三、使用AudioRecord 進行音頻捕獲。——從某個輸入,直接捕獲音頻數據:PCM格式
這種方法是3種之中最為靈活的,能讓開發者最大限度的處理采集的音頻,同時它捕獲到的音頻是原始音頻PCM格式的!像做變聲處理的需要就必須要用它收集音頻。在實際開發中,它也是最常用來采集音頻的手段。也是本文介紹的重點。
- //指定音頻源 這個和MediaRecorder是相同的
- int audioSource=MediaRecorder.AudioSource.MIC;
- //指定采樣率 (MediaRecoder 的采樣率通常是8000Hz CD的通常是44100Hz 不同的Android手機硬件將能夠以不同的采樣率進行采樣。其中11025是一個常見的采樣率)
- int sampleRateInHz=11025 ;
- //指定捕獲音頻的通道數目。在AudioFormat類中指定用於此的常量
- int channelConfig=AudioFormat.CHANNEL_CONFIGURATION_MONO;
- //指定音頻量化位數 ,在AudioFormaat類中指定了以下各種可能的常量。通常我們選擇ENCODING_PCM_16BIT和ENCODING_PCM_8BIT PCM代表的是脈沖編碼調制,它實際上是原始音頻樣本。
- //因此可以設置每個樣本的分辨率為16位或者8位,16位將占用更多的空間和處理能力,表示的音頻也更加接近真實。
- int audioFormat=AudioFormat.ENCODING_PCM_16BIT;
- 指定緩沖區大小。調用AudioRecord類的getMinBufferSize方法可以獲得。
- //創建AudioRecord。AudioRecord類實際上不會保存捕獲的音頻,因此需要手動創建文件並保存下載。
- AudioRecord record=new AudioRecord(audioSource,sampleRateInHz,channelConfig,audioFormat,bufferSizeInBytes);
布局xml文件和MediaRecorder Demo中一樣,2個按鈕而已!就不貼了,下面貼出AudioRecord的Demo的源代碼.
- public class MainActivity extends Activity implements OnClickListener {
- Button startRecordingButton, stopRecordingButton;//開始錄音、停止錄音
- File recordingFile;//儲存AudioRecord錄下來的文件
- boolean isRecording = false; //true表示正在錄音
- AudioRecord audioRecord=null;
- File parent=null;//文件目錄
- int bufferSize=0;//最小緩沖區大小
- int sampleRateInHz = 11025;//采樣率
- int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO; //單聲道
- int audioFormat = AudioFormat.ENCODING_PCM_16BIT; //量化位數
- String TAG="AudioRecord";
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- setContentView(R.layout.main);
- init();
- initListener();
- }
- //初始化
- public void init(){
- startRecordingButton = (Button)findViewById(R.id.StartRecordingButton);
- stopRecordingButton = (Button)findViewById(R.id.StopRecordingButton);
- bufferSize = AudioRecord.getMinBufferSize(sampleRateInHz,channelConfig, audioFormat);//計算最小緩沖區
- audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,sampleRateInHz,channelConfig, audioFormat, bufferSize);//創建AudioRecorder對象
- parent = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+ "/AudiioRecordTest");
- if(!parent.exists())
- parent.mkdirs();//創建文件夾
- }
- //初始化監聽器
- public void initListener(){
- startRecordingButton.setOnClickListener(this);
- stopRecordingButton.setOnClickListener(this);
- }
- public void onClick(View v) {
- switch (v.getId()) {
- //開始錄音
- case R.id.StartRecordingButton:
- {
- record();
- break;
- }
- //停止錄音
- case R.id.StopRecordingButton:
- {
- stopRecording();
- break;
- }
- }
- }
- //開始錄音
- public void record() {
- isRecording = true;
- new Thread(new Runnable() {
- @Override
- public void run() {
- isRecording = true;
- recordingFile = new File(parent,"audiotest.pcm");
- if(recordingFile.exists()){
- recordingFile.delete();
- }
- try {
- recordingFile.createNewFile();
- }
- catch (IOException e) {
- e.printStackTrace();
- Log.e(TAG,"創建儲存音頻文件出錯");
- }
- try {
- DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(recordingFile)));
- byte[] buffer = new byte[bufferSize];
- audioRecord.startRecording();//開始錄音
- int r = 0;
- while (isRecording) {
- int bufferReadResult = audioRecord.read(buffer,0,bufferSize);
- for (int i = 0; i < bufferReadResult; i++)
- {
- dos.write(buffer[i]);
- }
- r++;
- }
- audioRecord.stop();//停止錄音
- dos.close();
- } catch (Throwable t) {
- Log.e(TAG, "Recording Failed");
- }
- }
- }).start();
- }
- //停止錄音
- public void stopRecording()
- {
- isRecording = false;
- }
- }
注意這幾個Demo都要添加以下權限:
- <uses-permission android:name="android.permission.RECORD_AUDIO"/>
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
四、備注:
原始音頻PCM播放器 使用方法 : 文件->導入->裸數據 然后根據你錄音時的配置填寫相應參數 就可以播放了!