官方說(shuō)明
- AndioRecord大概說(shuō)明:
AndioRecord類的主要功能是讓各種JAVA應(yīng)用能夠管理音頻資源扫步,以便它們通過(guò)此類能夠錄制聲音相關(guān)的硬件所收集的聲音匈子。此功能的實(shí)現(xiàn)就是通過(guò)”pulling”(讀然⒍亍)AudioRecord對(duì)象的聲音數(shù)據(jù)來(lái)完成的其徙。在錄音過(guò)程中,應(yīng)用所需要做的就是通過(guò)后面三個(gè)類方法中的一個(gè)去及時(shí)地獲取AudioRecord對(duì)象的錄音數(shù)據(jù). AudioRecord類提供的三個(gè)獲取聲音數(shù)據(jù)的方法分別是read(byte[], int, int), read(short[], int, int), read(ByteBuffer, int).
無(wú)論選擇使用那一個(gè)方法都必須事先設(shè)定方便用戶的聲音數(shù)據(jù)的存儲(chǔ)格式晌区。
開(kāi)始錄音的時(shí)候朗若,AudioRecord需要初始化一個(gè)相關(guān)聯(lián)的聲音buffer
, 這個(gè)buffer主要是用來(lái)保存新的聲音數(shù)據(jù)哭懈。這個(gè)buffer的大小,我們可以在對(duì)象構(gòu)造期間去指定睬罗。它表明一個(gè)AudioRecord對(duì)象還沒(méi)有被讀热荽铩(同步)聲音數(shù)據(jù)前能錄多長(zhǎng)的音(即一次可以錄制的聲音容量)花盐。聲音數(shù)據(jù)從音頻硬件中被讀出菇爪,數(shù)據(jù)大小不超過(guò)整個(gè)錄音數(shù)據(jù)的大械手妗(可以分多次讀出),即每次讀取初始化buffer容量的數(shù)據(jù)
届囚。
2.AudioRecord對(duì)象創(chuàng)建
AudioRecord(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes)
audioSource 音頻源:指的是從哪里采集音頻奖亚。這里我們當(dāng)然是從麥克風(fēng)采集音頻析砸,所以此參數(shù)的值為MIC
sampleRateInHz 采樣率:音頻的采樣頻率首繁,每秒鐘能夠采樣的次數(shù)陨囊,采樣率越高胁塞,音質(zhì)越高。給出的實(shí)例是44100允懂、22050、11025但不限于這幾個(gè)參數(shù)生百。例如要采集低質(zhì)量的音頻就可以使用4000、8000等低采樣率。
channelConfig 聲道設(shè)置:android支持雙聲道立體聲和單聲道秕衙。MONO單聲道,STEREO立體聲
audioFormat 編碼制式和采樣大杏碌酢:采集來(lái)的數(shù)據(jù)當(dāng)然使用PCM編碼(脈沖代碼調(diào)制編碼,即PCM編碼。PCM通過(guò)抽樣啄枕、量化、編碼三個(gè)步驟將連續(xù)變化的模擬信號(hào)轉(zhuǎn)換為數(shù)字編碼及舍。) android支持的采樣大小16bit 或者8bit。當(dāng)然采樣大小越大攘残,那么信息量越多,音質(zhì)也越高,現(xiàn)在主流的采樣大小都是16bit泰涂,在低質(zhì)量的語(yǔ)音傳輸?shù)臅r(shí)候8bit足夠了。
bufferSizeInBytes 采集數(shù)據(jù)需要的緩沖區(qū)的大小,如果不知道最小需要的大小可以在getMinBufferSize()查看驳棱。
AudioRecord.getMinBufferSize(sampleRateInHz,channelConfig, channelConfig);
3.PCM 和 WAV文件
PCM
PCM是在由模擬信號(hào)向數(shù)字信號(hào)轉(zhuǎn)化的一種常用的編碼格式,稱為脈沖編碼調(diào)制罚渐,PCM將模擬信號(hào)按照一定的間距劃分為多段青扔,然后通過(guò)二進(jìn)制去量化每一個(gè)間距的強(qiáng)度微猖。PCM表示的是音頻文件中隨著時(shí)間的流逝的一段音頻的振幅。Android在WAV文件中支持PCM的音頻數(shù)據(jù)。WAV文件
WAV,MP3等是我們比較常見(jiàn)的音頻格式丝蹭,不同的編碼格式對(duì)原始音頻采用的編碼方式也是不同的,通常為了方便傳輸?shù)葐?wèn)題犁享,會(huì)對(duì)原始音頻進(jìn)行壓縮,同時(shí)為了能夠使得播放器能夠識(shí)別該種格式桨吊,所以在每種格式的頭文件都是特定的凤巨,有一定的規(guī)則,來(lái)讓播放器識(shí)別出是該種格式炊林,然后按著相應(yīng)的解碼算法去播放后面的音頻文件渣聚。
4.代碼運(yùn)行過(guò)程
首先是創(chuàng)建AudioRecord對(duì)象
//音頻輸入-麥克風(fēng)
private final static int AUDIO_INPUT = MediaRecorder.AudioSource.MIC;
//采用頻率
//44100是目前的標(biāo)準(zhǔn)僧叉,但是某些設(shè)備仍然支持22050,16000隘道,11025
//采樣頻率一般共分為22.05KHz激捏、44.1KHz、48KHz三個(gè)等級(jí)
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;
// 緩沖區(qū)字節(jié)大小
private int bufferSizeInBytes = 0;
//錄音對(duì)象
private AudioRecord audioRecord;
/**
* 創(chuàng)建默認(rèn)的錄音對(duì)象
*
* @param fileName 文件名
*/
public void createDefaultAudio(String fileName) {
// 獲得緩沖區(qū)字節(jié)大小
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;
}
開(kāi)始錄音例诀,同時(shí)開(kāi)個(gè)子線程將錄音的數(shù)據(jù)放入pcm文件
audioRecord.startRecording();
new Thread(new Runnable() {
@Override
public void run() {
writeDataTOFile(listener);
}
}).start();
如何將音頻寫(xiě)入文件是重點(diǎn),首先創(chuàng)建pcm文件背犯,得到他的FileOutputStream,然后不斷循環(huán)AudioRecord通過(guò)read將錄音的數(shù)據(jù)放入字節(jié)數(shù)組里,當(dāng)錄音結(jié)束的時(shí)候要記得停止這個(gè)循環(huán)
// new一個(gè)byte數(shù)組用來(lái)存一些字節(jié)數(shù)據(jù)瞧毙,大小為緩沖區(qū)大小
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);// 建立一個(gè)可存取字節(jié)的文件
} 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());
}
}
}
如何我們要實(shí)現(xiàn)能夠暫停錄音檀训,只要AudioRecord.stop就行览露,然后當(dāng)繼續(xù)錄音時(shí)在AudioRecord.start就好了脐恩,但是要另創(chuàng)建一個(gè)pcm記錄韵卤,當(dāng)錄音結(jié)束時(shí)我們要將這些pcm一起轉(zhuǎn)換為一個(gè)wav