本篇項目地址,名字是AudioRecord錄音(能暫停,將pch轉換爲wav),求star
https://github.com/979451341/Audio-and-video-learning-materials
先來段官方說明
html
AndioRecord類的主要功能是讓各類JAVA應用可以管理音頻資源,以便它們經過此類可以錄製聲音相關的硬件所收集的聲音。此功能的實現就是經過」pulling」(讀取)AudioRecord對象的聲音數據來完成的。在錄音過程當中,應用所須要作的就是經過後面三個類方法中的一個去及時地獲取AudioRecord對象的錄音數據. AudioRecord類提供的三個獲取聲音數據的方法分別是read(byte[], int, int), read(short[], int, int), read(ByteBuffer, int). 不管選擇使用那一個方法都必須事先設定方便用戶的聲音數據的存儲格式。
開始錄音的時候,AudioRecord須要初始化一個相關聯的聲音buffer, 這個buffer主要是用來保存新的聲音數據。這個buffer的大小,咱們能夠在對象構造期間去指定。它代表一個AudioRecord對象尚未被讀取(同步)聲音數據前能錄多長的音(即一次能夠錄製的聲音容量)。聲音數據從音頻硬件中被讀出,數據大小不超過整個錄音數據的大小(能夠分屢次讀出),即每次讀取初始化buffer容量的數據。
android
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);
git
PCM
PCM是在由模擬信號向數字信號轉化的一種經常使用的編碼格式,稱爲脈衝編碼調製,PCM將模擬信號按照必定的間距劃分爲多段,而後經過二進制去量化每個間距的強度。PCM表示的是音頻文件中隨着時間的流逝的一段音頻的振幅。Android在WAV文件中支持PCM的音頻數據。
WAV文件
WAV,MP3等是咱們比較常見的音頻格式,不一樣的編碼格式對原始音頻採用的編碼方式也是不一樣的,一般爲了方便傳輸等問題,會對原始音頻進行壓縮,同時爲了可以使得播放器可以識別該種格式,因此在每種格式的頭文件都是特定的,有必定的規則,來讓播放器識別出是該種格式,而後按着相應的解碼算法去播放後面的音頻文件。
github
首先是建立和配置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將錄音的數據放入字節數組裏,當錄音結束的時候要記得中止這個循環ide
// 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
this