您好,登錄后才能下訂單哦!
AudioRecord類相對于MediaRecorder來說,更加接近底層,為我們封裝的方法也更少。然而實現一個AudioRecord的音頻錄制程序也很簡單。本實例代碼如下:
package demo.camera; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import android.app.Activity; import android.content.ContentValues; import android.content.Intent; import android.hardware.Camera.AutoFocusCallback; import android.media.AudioFormat; import android.media.AudioManager; import android.media.AudioRecord; import android.media.AudioTrack; import android.media.MediaPlayer; import android.media.MediaRecorder; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView; /** * 該實例中,我們使用AudioRecord類來完成我們的音頻錄制程序 * AudioRecord類,我們可以使用三種不同的read方法來完成錄制工作, * 每種方法都有其實用的場合 * 一、實例化一個AudioRecord類我們需要傳入幾種參數 * 1、AudioSource:這里可以是MediaRecorder.AudioSource.MIC * 2、SampleRateInHz:錄制頻率,可以為8000hz或者11025hz等,不同的硬件設備這個值不同 * 3、ChannelConfig:錄制通道,可以為AudioFormat.CHANNEL_CONFIGURATION_MONO和AudioFormat.CHANNEL_CONFIGURATION_STEREO * 4、AudioFormat:錄制編碼格式,可以為AudioFormat.ENCODING_16BIT和8BIT,其中16BIT的仿真性比8BIT好,但是需要消耗更多的電量和存儲空間 * 5、BufferSize:錄制緩沖大小:可以通過getMinBufferSize來獲取 * 這樣我們就可以實例化一個AudioRecord對象了 * 二、創建一個文件,用于保存錄制的內容 * 同上篇 * 三、打開一個輸出流,指向創建的文件 * DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file))) * 四、現在就可以開始錄制了,我們需要創建一個字節數組來存儲從AudioRecorder中返回的音頻數據,但是 * 注意,我們定義的數組要小于定義AudioRecord時指定的那個BufferSize * short[]buffer = new short[BufferSize/4]; * startRecording(); * 然后一個循環,調用AudioRecord的read方法實現讀取 * 另外使用MediaPlayer是無法播放使用AudioRecord錄制的音頻的,為了實現播放,我們需要 * 使用AudioTrack類來實現 * AudioTrack類允許我們播放原始的音頻數據 * * * 一、實例化一個AudioTrack同樣要傳入幾個參數 * 1、StreamType:在AudioManager中有幾個常量,其中一個是STREAM_MUSIC; * 2、SampleRateInHz:最好和AudioRecord使用的是同一個值 * 3、ChannelConfig:同上 * 4、AudioFormat:同上 * 5、BufferSize:通過AudioTrack的靜態方法getMinBufferSize來獲取 * 6、Mode:可以是AudioTrack.MODE_STREAM和MODE_STATIC,關于這兩種不同之處,可以查閱文檔 * 二、打開一個輸入流,指向剛剛錄制內容保存的文件,然后開始播放,邊讀取邊播放 * * 實現時,音頻的錄制和播放分別使用兩個AsyncTask來完成 */ public class MyAudioRecord2 extends Activity{ private TextView stateView; private Button btnStart,btnStop,btnPlay,btnFinish; private RecordTask recorder; private PlayTask player; private File audioFile; private boolean isRecording=true, isPlaying=false; //標記 private int frequence = 8000; //錄制頻率,單位hz.這里的值注意了,寫的不好,可能實例化AudioRecord對象的時候,會出錯。我開始寫成11025就不行。這取決于硬件設備 private int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO; private int audioEncoding = AudioFormat.ENCODING_PCM_16BIT; public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.my_audio_record); stateView = (TextView)this.findViewById(R.id.view_state); stateView.setText("準備開始"); btnStart = (Button)this.findViewById(R.id.btn_start); btnStop = (Button)this.findViewById(R.id.btn_stop); btnPlay = (Button)this.findViewById(R.id.btn_play); btnFinish = (Button)this.findViewById(R.id.btn_finish); btnFinish.setText("停止播放"); btnStop.setEnabled(false); btnPlay.setEnabled(false); btnFinish.setEnabled(false); //在這里我們創建一個文件,用于保存錄制內容 File fpath = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/data/files/"); fpath.mkdirs();//創建文件夾 try { //創建臨時文件,注意這里的格式為.pcm audioFile = File.createTempFile("recording", ".pcm", fpath); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void onClick(View v){ int id = v.getId(); switch(id){ case R.id.btn_start: //開始錄制 //這里啟動錄制任務 recorder = new RecordTask(); recorder.execute(); break; case R.id.btn_stop: //停止錄制 this.isRecording = false; //更新狀態 //在錄制完成時設置,在RecordTask的onPostExecute中完成 break; case R.id.btn_play: player = new PlayTask(); player.execute(); break; case R.id.btn_finish: //完成播放 this.isPlaying = false; break; } } class RecordTask extends AsyncTask<Void, Integer, Void>{ @Override protected Void doInBackground(Void... arg0) { isRecording = true; try { //開通輸出流到指定的文件 DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(audioFile))); //根據定義好的幾個配置,來獲取合適的緩沖大小 int bufferSize = AudioRecord.getMinBufferSize(frequence, channelConfig, audioEncoding); //實例化AudioRecord AudioRecord record = new AudioRecord(MediaRecorder.AudioSource.MIC, frequence, channelConfig, audioEncoding, bufferSize); //定義緩沖 short[] buffer = new short[bufferSize]; //開始錄制 record.startRecording(); int r = 0; //存儲錄制進度 //定義循環,根據isRecording的值來判斷是否繼續錄制 while(isRecording){ //從bufferSize中讀取字節,返回讀取的short個數 //這里老是出現buffer overflow,不知道是什么原因,試了好幾個值,都沒用,TODO:待解決 int bufferReadResult = record.read(buffer, 0, buffer.length); //循環將buffer中的音頻數據寫入到OutputStream中 for(int i=0; i<bufferReadResult; i++){ dos.writeShort(buffer[i]); } publishProgress(new Integer(r)); //向UI線程報告當前進度 r++; //自增進度值 } //錄制結束 record.stop(); Log.v("The DOS available:", "::"+audioFile.length()); dos.close(); } catch (Exception e) { // TODO: handle exception } return null; } //當在上面方法中調用publishProgress時,該方法觸發,該方法在UI線程中被執行 protected void onProgressUpdate(Integer...progress){ stateView.setText(progress[0].toString()); } protected void onPostExecute(Void result){ btnStop.setEnabled(false); btnStart.setEnabled(true); btnPlay.setEnabled(true); btnFinish.setEnabled(false); } protected void onPreExecute(){ //stateView.setText("正在錄制"); btnStart.setEnabled(false); btnPlay.setEnabled(false); btnFinish.setEnabled(false); btnStop.setEnabled(true); } } class PlayTask extends AsyncTask<Void, Integer, Void>{ @Override protected Void doInBackground(Void... arg0) { isPlaying = true; int bufferSize = AudioTrack.getMinBufferSize(frequence, channelConfig, audioEncoding); short[] buffer = new short[bufferSize/4]; try { //定義輸入流,將音頻寫入到AudioTrack類中,實現播放 DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream(audioFile))); //實例AudioTrack AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC, frequence, channelConfig, audioEncoding, bufferSize, AudioTrack.MODE_STREAM); //開始播放 track.play(); //由于AudioTrack播放的是流,所以,我們需要一邊播放一邊讀取 while(isPlaying && dis.available()>0){ int i = 0; while(dis.available()>0 && i<buffer.length){ buffer[i] = dis.readShort(); i++; } //然后將數據寫入到AudioTrack中 track.write(buffer, 0, buffer.length); } //播放結束 track.stop(); dis.close(); } catch (Exception e) { // TODO: handle exception } return null; } protected void onPostExecute(Void result){ btnPlay.setEnabled(true); btnFinish.setEnabled(false); btnStart.setEnabled(true); btnStop.setEnabled(false); } protected void onPreExecute(){ //stateView.setText("正在播放"); btnStart.setEnabled(false); btnStop.setEnabled(false); btnPlay.setEnabled(false); btnFinish.setEnabled(true); } } }
可惜,本實例測試時有個問題,在錄制的時候,會出現buffer over。緩存泄露,待解決。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。