android手機的Mic對聲音的感知

2021-06-01 13:02:25 字數 2718 閱讀 5627

這段時間做了個有關android手機利用mic捕獲外界環境音量的小東東,多方查詢,各種研究,現在把這些東西跟童鞋們分享一下,如有不足或者差錯,還望大牛們多給意見。

android提供可以實現錄音功能的有audiorecord和mediarecorder,其中audiorecord是讀取mic的音訊流,可以邊錄音邊分析流的資料;而mediarecorder則能夠直接把mic的資料存到檔案,並且能夠進行編碼(如amr,***等)。

首先,要將你的應用加入許可權(無論你是使用audiorecord還是mediarecorder):

然後,分開介紹兩者的用法。

《!--audiorecord--》

1、新建錄音取樣類,實現介面:

public class micsensor implements audiorecord.onrecordpositionupdatelistener

2、關於audiorecord的初始化:

public audiorecord (int audiosource, int samplerateinhz, int channelconfig, int audioformat, int buffersizeinbytes)

audiosource:              錄音源(例如:mediarecorder.audiosource.mic    指定mic為錄音源)

samplerateinhz:        預設的取樣頻率,單位為hz。(常用的如44100hz

、22050hz、16000hz、11025hz、8000hz,有人說44100hz是目前保證在所有廠商的android手機上都能使用的取樣頻率,但是個人在三星i9000上使用卻不然,經測試8000hz似乎更為靠譜

)  

channelconfig:           描述音訊通道設定。(在此我使用了audioformat.channel_configuration_mono)

audioformat:              音訊資料支援格式。(這個好像跟聲道有關,16bit的脈碼調變錄音應該是所謂的雙聲道,而8bit脈碼調變錄音是單聲道。audioformat.encoding_pcm_16bit、audioformat.encoding_pcm_8bit)

buffersizeinbytes:        在錄製過程中,音訊資料寫入緩衝區的總數(位元組)。 從緩衝區讀取的新音訊資料總會小於此值。 getminbuffersize(int, int, int)返回audiorecord 例項建立成功後的最小緩衝區。 設定的值比getminbuffersize()還小則會導致初始化失敗。

3、初始化成功後則可啟動錄音    audiorecord.startrecording()

4、編寫執行緒類將錄音資料讀入緩衝區,進行分析

short buffer = new short[buffersize];              //short型別對應16bit音訊資料格式,byte型別對應於8bit

audiorecord.read(buffer, 0, buffersize);            //返回值是個int型別的資料長度值

5、在此需要對buffer中的資料進行一些說明:

這樣讀取的資料是在時域下的資料,直接用於計算沒有任何實際意義。需要將時域下的資料轉化為頻域下的資料,才能訴諸於計算。

頻域(frequency domain)是指在對函式或訊號進行分析時,分析其和頻率有關部份,而不是和時間有關的部份。

函式或訊號可以透過一對數學的運運算元在時域及頻域之間轉換。例如傅利葉變換可以將乙個時域訊號轉換成在不同頻率下對應的振幅及相位,其頻譜就是時域訊號在頻域下的表現,而反傅利葉變換可以將頻譜再轉換回時域的訊號。

訊號在時域下的圖形可以顯示訊號如何隨著時間變化,而訊號在頻域下的圖形(一般稱為頻譜)可以顯示訊號分布在哪些頻率及其比例。頻域的表示法除了有各個頻率下的大小外,也會有各個頻率的相位,利用大小及相位的資訊可以將各頻率的弦波給予不同的大小及相位,相加以後可以還原成原始的訊號。

經傅利葉變化後得到的複數陣列是個二維陣列,實部和虛部的平方和取對數後乘以10就大致等於我們通常表示音量的分貝了。

《!--mediarecorder--》

相對於audiorecord,mediarecorder提供了更為簡單的api。

mediarecorder = new mediarecorder();

mediarecorder.setaudiosource(mediarecorder.audiosource.mic);

mediarecorder.setoutputformat(mediarecorder.outputformat.three_gpp);

mediarecorder.setaudioencoder(mediarecorder.audioencoder.amr_nb);

mediarecorder.setoutputfile("/dev/null");

設定好mediarecorder的各個屬性,然後通過執行緒呼叫方法  mediarecorder.getmaxamplitude();

得到的是瞬時的最大振幅,直接取對數然後乘以10就可以表徵分貝了。

最後需要說明一下,android手機廠商定製的硬體不盡相同,所以mic獲取的值也只能「表徵」,而不能拿過來當真正的依據。它們雖是智慧型手機,但也還是手機,機械人不是人!呵呵。。。

對了,每個手機mic在聲訊號和電訊號進行轉換時都有做過電容保護,為了其不因外界環境的過於嘈雜而易受到損壞。所以超聲波和次聲波,我們人不容易接受的聲音,手機也不會入耳的。

Android 獲取手機的手機號

1.獲取手機號 telephonymanager telephonymanager telephonymanager getsystemservice context.telephony service string line1number telephonymanager.getline1numb...

Android手機上的Logcat

最近開發電池方面的軟體,有時需要測試usb線被拔下後軟體的狀態,但是一旦拔下了,就看不到logcat的輸出,還好,自己能夠寫乙個手機上的logcat,那樣即使拔下了usb線,也能隨時看。簡介如果您是android程式設計師,您一定離不開logcat,但測試總會遇到一些不能連線usb資料線的時候,怎麼...

Android手機的眾多折騰

也許是看大家都在折騰android手機,所以一直懶得折騰,但昨天又需要用它測試乙個東西,卻死活不得要領,從安裝到結束,到手機的使用,都遇到麻煩。所以痛下決心,把手機折騰一下。手機是電信送的c8500,開始不想大動,就把一些沒用的程式關掉就行了。刪程式。用91程式助手就行。這個程式不錯,自動安裝驅動,...