簡(jiǎn)介
Android中誓琼,如果要錄制音頻的話有兩個(gè)選擇,一個(gè)是MediaRecorder
,另一個(gè)就是AudioRecord
腹侣,前者使用簡(jiǎn)單叔收,后者就相對(duì)復(fù)雜點(diǎn)
關(guān)于MediaRecorder
的用法相信大家都比較熟悉,而對(duì)于AudioRecord
可能要陌生一些傲隶,所有我們重點(diǎn)來(lái)講下AudioRecord
的用法
聲音
在此之前饺律,我們先來(lái)了解下關(guān)于聲音的知識(shí),下面是來(lái)自百度百科的介紹
聲音(sound)是由物體振動(dòng)產(chǎn)生的聲波跺株。是通過(guò)介質(zhì)(空氣或固體复濒、液體)傳播并能被人或動(dòng)物聽(tīng)覺(jué)器官所感知的波動(dòng)現(xiàn)象。最初發(fā)出振動(dòng)(震動(dòng))的物體叫聲源乒省。聲音以波的形式振動(dòng)(震動(dòng))傳播。聲音是聲波通過(guò)任何物質(zhì)傳播形成的運(yùn)動(dòng)洛二。
聲音作為一種波,頻率在20 Hz~20 kHz之間的聲音是可以被人耳識(shí)別的晾嘶。
從上面所述我們得到一個(gè)信息:人耳可以聽(tīng)到20 Hz~20 kHz的聲音垒迂,那么根據(jù)奈奎斯特定律妒蛇,采樣率要大于或等于信號(hào)中兩倍的最高頻率机断,這樣才能完整得保留原始信號(hào)中的信息
也就是說(shuō)绣夺,要一秒鐘采樣40k次,才能無(wú)失幀得記錄原始信息
計(jì)算機(jī)中記錄原始音頻奋蔚,一般是用PCM格式存儲(chǔ)烈钞,pcm的內(nèi)容都是byte類(lèi)型的數(shù)組,也就是編碼格式
PCM8位
如果是單聲道馒过,那么byte數(shù)組每一個(gè)元素都是一次采樣的數(shù)據(jù)
如果是雙聲道酗钞,那么byte數(shù)組就是LRLRLR形式的存儲(chǔ)(L代表左耳,R代表右耳)
PCM16位
如果是單聲道留凭,那么byte數(shù)組每?jī)蓚€(gè)元素都是一次采樣的數(shù)據(jù)
如果是雙聲道,那么byte數(shù)組就是L低L高 R低R高 L低L高 R低R高形式的存儲(chǔ)(L代表左耳兼耀,R代表右耳)求冷,低表示低八位,高表示高八位
綜上我們得出關(guān)于音頻的三個(gè)參數(shù)
- 采樣率
- 聲道數(shù)
- 編碼格式
創(chuàng)建AudioRecord
private static final int AUDIO_INPUT = MediaRecorder.AudioSource.MIC;//音頻來(lái)源
private static final int AUDIO_SAMPLE_RATE = 44100;//采樣率
private static final int AUDIO_IN_CHANNEL = AudioFormat.CHANNEL_IN_STEREO;//雙聲道
private static final int AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;//編碼格式 PCM 16位
private int bufferSizeInBytes = 0;//最小錄音緩存
private AudioRecord mAudioRecord;//AudioRecord
public void createDefaultAudio() {
bufferSizeInBytes = AudioRecord.getMinBufferSize(AUDIO_SAMPLE_RATE, AUDIO_IN_CHANNEL, AUDIO_ENCODING);
mAudioRecord = new AudioRecord(AUDIO_INPUT, AUDIO_SAMPLE_RATE, AUDIO_IN_CHANNEL, AUDIO_ENCODING, bufferSizeInBytes);
}
我們創(chuàng)建AudioRecord
之前還需要獲得一個(gè)叫做最小緩存bufferSizeInBytes
的東西拯坟,它可以通過(guò)AudioRecord.getMinBufferSize()
方法獲取郁季,因?yàn)槲覀冧浺粜枰粩嗳プx寫(xiě)钱磅,所有需要有一個(gè)緩存空間盖淡,剛好AudioRecord提供給我們現(xiàn)成的方法,我們直接用就可以了褪迟。
我們創(chuàng)建成功就可以開(kāi)始錄音了味赃,不過(guò)要注意,此時(shí)你要檢查你的應(yīng)用是否有錄音的權(quán)限
錄音
mAudioRecord.startRecording();
開(kāi)啟錄音后我們還沒(méi)做任何事渴丸,也就沒(méi)法將錄音保存下來(lái)另凌,所有我們得開(kāi)啟一個(gè)子線程將數(shù)據(jù)寫(xiě)入文件
開(kāi)啟錄音線程
/**
* 開(kāi)啟錄制音頻子線程
*/
private void startRecordThread() {
new Thread(new Runnable() {
@Override
public void run() {
writeDataToFile();
}
}).start();
}
/**
* 將錄音內(nèi)容寫(xiě)入文件
*/
private void writeDataToFile() {
byte[] audioData = new byte[bufferSizeInBytes];
FileOutputStream fos = null;
int readSize = 0;
try {
File file = new File("你的文件路徑");
if (file.exists()) {
file.delete();
}
fos = new FileOutputStream("你的文件路徑", true);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
while (!isStop) {
readSize = mAudioRecord.read(audioData, 0, bufferSizeInBytes);
if (readSize == AudioRecord.ERROR_INVALID_OPERATION || readSize == AudioRecord.ERROR_BAD_VALUE) {
continue;
}
if (fos != null) {
try {
fos.write(audioData);
} catch (IOException e) {
e.printStackTrace();
}
}
}
try {
if (fos != null) {
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
我們這個(gè)線程有一個(gè)無(wú)線循環(huán)的while,在while里我們進(jìn)行數(shù)據(jù)的讀寫(xiě)诗茎,我們可以定義一個(gè)boolean變量isStop來(lái)控制錄音的停止
我們先是新建了一個(gè)byte數(shù)組
byte[] audioData = new byte[bufferSizeInBytes]
這個(gè)數(shù)組大小就是之前我們獲取到的最小緩存
接著我們打開(kāi)文件,進(jìn)行讀寫(xiě)王污,通過(guò)mAudioRecord.read()
方法不斷從AudioRecord中讀取數(shù)據(jù),然后將其寫(xiě)入文件中尿招,最后在我們停止之后關(guān)閉文件的輸出流阱驾。
停止錄音
/**
* 停止錄音
*/
private void stop(){
mAudioRecord.stop();
isStop = ture;
}
停止錄音就調(diào)用AudioRecord
的stop()
方法并將isStop置為ture即可停止錄音
最后
以上就是AudioRecord的基本用法里覆,關(guān)于音頻的更多知識(shí)與應(yīng)用后面會(huì)陸續(xù)和大家分享,希望大家能夠喜歡喧枷。