最近做的項目是和語音即時採集並發送,對方即時接收並播放相關,下面記錄下實現的核心代碼。
很多Android開發人員應該知道android有個MediaRecorder對象和MediaPlayer對象,用於錄製和播放音頻。這個弊端在於他們不能即時採集並發送出去,所以,我們只能使用AudioRecord和AudioTrack來實現。
記得申明許可權:
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /><uses-permission android:name="android.permission.RECORD_AUDIO" >
一、AudioRecord實現核心代碼介紹如下:
1、先申明相關錄製配置參數
private AudioRecord audioRecord;// 錄音對象private int frequence = 8000;// 採樣率 8000private int channelInConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;// 定義採樣通道private int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;// 定義音頻編碼(16位)private byte[] buffer = null;// 錄製的緩衝數組
2、在開始錄製前,我們需要初始化AudioRecord類。
// 根據定義好的幾個配置,來擷取合適的緩衝大小// int bufferSize = 800;int bufferSize = AudioRecord.getMinBufferSize(frequence, channelInConfig, audioEncoding);// 執行個體化AudioRecordaudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, frequence, channelInConfig, audioEncoding, bufferSize);// 定義緩衝數組buffer = new byte[bufferSize];
3、準備開始錄製,使用迴圈不斷讀取資料。
audioRecord.startRecording();// 開始錄製isRecording = true;// 設定錄製標記為true// 開始錄製while (isRecording) {// 錄製的內容放置到了buffer中,result代表格儲存體長度int result = audioRecord.read(buffer, 0, buffer.length);/*.....result為buffer中錄製資料的長度(貌似基本上都是640)。剩下就是處理buffer了,是發送出去還是直接播放,這個隨便你。*/}//錄製迴圈結束後,記得關閉錄製!!if (audioRecord != null) { audioRecord.stop();}
二、AudioTrack代碼實現介紹如下:
1、聲明播放相關配置。
private AudioTrack track = null;// 錄音檔案播放對象private int frequence = 8000;// 採樣率 8000private int channelInConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;// 定義採樣通道private int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;// 定義音頻編碼(16位)private int bufferSize = -1;// 播放緩衝大小
2、初始化AudioTrack對象(初始化一次,該對象可重複使用)
// 擷取緩衝 大小bufferSize = AudioTrack.getMinBufferSize(frequence, channelInConfig, audioEncoding);// 執行個體AudioTracktrack = new AudioTrack(AudioManager.STREAM_MUSIC, frequence, channelInConfig, audioEncoding, bufferSize, AudioTrack.MODE_STREAM);
3、使用AudioTrack播放語音資料。
//將語音資料寫入即可。track.write(dataArray, buffer, len);
問題一:
由於目前的項目是即時採集,即時發送,所以需要考慮到包的大小,經測試,我們使用160個byte作為一個包傳遞可以做到比較良好的播放效果(也就是將一份buffer拆分成四個發送)。處理代碼如下:
// 將資料通過監聽介面回調出去if (audioRecordingCallback != null) { int offset = result % MAX_DATA_LENGTH > 0 ? 1 : 0; //將一個buffer拆分成幾份小資料包 MAX_DATA_LENGTH 為包的最大byte數 for (int i = 0; i < result / MAX_DATA_LENGTH + offset; i++) { int length = MAX_DATA_LENGTH; if ((i + 1) * MAX_DATA_LENGTH > result) { length = result - i * MAX_DATA_LENGTH; } //寫到回調介面 audioRecordingCallback.onRecording(buffer, i * MAX_DATA_LENGTH, length); }}
問題二:
有時候傳輸的過來播放聲音會一卡一卡的,為瞭解決這樣的問題,暫時使用了語音雙緩衝機制來解決,問題最佳化很明顯。代碼和示意圖如下:
以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支援雲棲社區。