本篇項目地址,名字是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