本篇項目地址,名字是AudioRecord錄音(能暫停,將pch轉換為wav),求starhttps://github.com/979451341/Audio-and-video-learning-materials先來段官方說明 1.AndioRecord大概說明 AndioRecord類的主要功 ...
本篇項目地址,名字是AudioRecord錄音(能暫停,將pch轉換為wav),求star
https://github.com/979451341/Audio-and-video-learning-materials
先來段官方說明
1.AndioRecord大概說明
AndioRecord類的主要功能是讓各種JAVA應用能夠管理音頻資源,以便它們通過此類能夠錄製聲音相關的硬體所收集的聲音。此功能的實現就是通過”pulling”(讀取)AudioRecord對象的聲音數據來完成的。在錄音過程中,應用所需要做的就是通過後面三個類方法中的一個去及時地獲取AudioRecord對象的錄音數據.
AudioRecord類提供的三個獲取聲音數據的方法分別是read(byte[], int, int), read(short[], int,
int), read(ByteBuffer, int). 無論選擇使用那一個方法都必須事先設定方便用戶的聲音數據的存儲格式。
開始錄音的時候,AudioRecord需要初始化一個相關聯的聲音buffer,
這個buffer主要是用來保存新的聲音數據。這個buffer的大小,我們可以在對象構造期間去指定。它表明一個AudioRecord對象還沒有被讀取(同步)聲音數據前能錄多長的音(即一次可以錄製的聲音容量)。聲音數據從音頻硬體中被讀出,數據大小不超過整個錄音數據的大小(可以分多次讀出),即每次讀取初始化buffer容量的數據。
2.AudioRecord對象創建
AudioRecord(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes)
audioSource
音頻源:指的是從哪裡採集音頻。這裡我們當然是從麥克風采集音頻,所以此參數的值為MIC
sampleRateInHz
採樣率:音頻的採樣頻率,每秒鐘能夠採樣的次數,採樣率越高,音質越高。給出的實例是44100、22050、11025但不限於這幾個參數。例如要採集低質量的音頻就可以使用4000、8000等低採樣率。
channelConfig
聲道設置:android支持雙聲道立體聲和單聲道。MONO單聲道,STEREO立體聲
audioFormat
編碼制式和採樣大小:採集來的數據當然使用PCM編碼(脈衝代碼調製編碼,即PCM編碼。PCM通過抽樣、量化、編碼三個步驟將連續變化的模擬信號轉換為數字編碼。)
android支持的採樣大小16bit
或者8bit。當然採樣大小越大,那麼信息量越多,音質也越高,現在主流的採樣大小都是16bit,在低質量的語音傳輸的時候8bit足夠了。
bufferSizeInBytes
採集數據需要的緩衝區的大小,如果不知道最小需要的大小可以在getMinBufferSize()查看。
AudioRecord.getMinBufferSize(sampleRateInHz,
channelConfig, channelConfig);
3.PCM和WAV文件
PCM
PCM是在由模擬信號向數字信號轉化的一種常用的編碼格式,稱為脈衝編碼調製,PCM將模擬信號按照一定的間距劃分為多段,然後通過二進位去量化每一個間距的強度。PCM表示的是音頻文件中隨著時間的流逝的一段音頻的振幅。Android在WAV文件中支持PCM的音頻數據。
WAV文件
WAV,MP3等是我們比較常見的音頻格式,不同的編碼格式對原始音頻採用的編碼方式也是不同的,通常為了方便傳輸等問題,會對原始音頻進行壓縮,同時為了能夠使得播放器能夠識別該種格式,所以在每種格式的頭文件都是特定的,有一定的規則,來讓播放器識別出是該種格式,然後按著相應的解碼演算法去播放後面的音頻文件。
4.代碼運行過程
首先是創建和配置AudioRecord
//音頻輸入-麥克風 private final static int AUDIO_INPUT = MediaRecorder.AudioSource.MIC; //採用頻率 //44100是目前的標準,但是某些設備仍然支持22050,16000,11025 //採樣頻率一般共分為22.05KHz、44.1KHz、48KHz三個等級 private final static int AUDIO_SAMPLE_RATE = 16000; //聲道 單聲道 private final static int AUDIO_CHANNEL = AudioFormat.CHANNEL_IN_MONO; //編碼 private final static int AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT; // 緩衝區位元組大小 private int bufferSizeInBytes = 0; //錄音對象 private AudioRecord audioRecord; /** * 創建預設的錄音對象 * * @param fileName 文件名 */ public void createDefaultAudio(String fileName) { // 獲得緩衝區位元組大小 bufferSizeInBytes = AudioRecord.getMinBufferSize(AUDIO_SAMPLE_RATE, AUDIO_CHANNEL, AUDIO_ENCODING); audioRecord = new AudioRecord(AUDIO_INPUT, AUDIO_SAMPLE_RATE, AUDIO_CHANNEL, AUDIO_ENCODING, bufferSizeInBytes); this.fileName = fileName; status = Status.STATUS_READY; }
開始錄音,同時開個子線程將錄音的數據放入pcm文件
audioRecord.startRecording(); new Thread(new Runnable() { @Override public void run() { writeDataTOFile(listener); } }).start();
如何將音頻寫入文件是重點,我寫個偽代碼,說明這個代碼運行順序
首先創建pcm文件,得到他的FileOutputStream,然後不斷迴圈AudioRecord通過read將錄音的數據放入位元組數組裡,當錄音結束的時候要記得停止這個迴圈
// new一個byte數組用來存一些位元組數據,大小為緩衝區大小 byte[] audiodata = new byte[bufferSizeInBytes]; FileOutputStream fos = null; int readsize = 0; try { File file = new File(currentFileName); if (file.exists()) { file.delete(); } fos = new FileOutputStream(file);// 建立一個可存取位元組的文件 } catch (IllegalStateException e) { Log.e("AudioRecorder", e.getMessage()); throw new IllegalStateException(e.getMessage()); } catch (FileNotFoundException e) { Log.e("AudioRecorder", e.getMessage()); } while (true) { readsize = audioRecord.read(audiodata, 0, bufferSizeInBytes); if (AudioRecord.ERROR_INVALID_OPERATION != readsize && fos != null) { try { fos.write(audiodata); } catch (IOException e) { Log.e("AudioRecorder", e.getMessage()); } } }
如何我們要實現能夠暫停錄音,只要AudioRecord.stop就行,然後當繼續錄音時在AudioRecord.start就好了,但是要另創建一個pcm記錄,當錄音結束時我們要將這些pcm一起轉換為一個wav,
至於pcm轉換為wav的代碼是固定的,我就不貼出,大家在文章首部代碼地址自取吧
參考文章
http://blog.csdn.net/hellofeiya/article/details/8968534
http://blog.csdn.net/JenseaChen/article/details/46883319