當前位置:首頁 » 安卓系統 » android音頻時間

android音頻時間

發布時間: 2024-09-22 17:53:51

⑴ Android Audio簡述

audio是Android系統是比較重要的一個模塊,本人也涉足時間不是很長,經驗還是很少的,只是把自己在工作中所遇到的問題記錄。

Audio 即音頻, 也就是控制著手機中的各種聲音的輸出,比如說,音樂的播放,音量大小,按鍵音,插入耳機,聲音從耳機播放,連接藍牙,聲音從藍牙耳機中播放。還有一些HiFi播放, offload播放,高清播放。

常見的問題如下:

POP音,漏音,聲音卡頓,耳機無法識別,還有一些音頻通路等問題,還有一些穩定性的問題如:ANR、CRASH、tombstone。還有一些安全漏洞的問題(主要是核心庫那裡)。

回歸正題

-------華麗的分割線-------

audio分為  應用層,fwk層,native fwk, hal層。

常見的文件有MediaPlayer.java、 AudioSystem.java、 AudioService.java、AudioManager.java 文件路徑(framework/base/media)

AudioFlinger.cpp、AudioTrack.cpp、 AudioPolicyManager.cpp、 Threads.cpp、Tracks.cpp、 Engine.cpp、 Audiosystem.cpp  文件路徑(framework/av)

audio_hw.c  文件路徑(vendor/)

java文件我在這里就不過多的說了,沒啥好講的,主要說一下c++文件吧。

AudioFlinger 是音頻策略的執行者, AudioPolicyManager是製作音頻策略的,AudioTrack是負責播放從上層傳過來的PCM數據,簡單的說就是負責播放的。 

audio_hw 是每個HAL層的文件,每個手機廠商自己定製的文件。當然Google也有。

一般呢,我們處理音頻相關的問題呢,有一些特定的套路,需要AP 側的log, 有時還需要kernel 的log,  當然最主要的是需要音頻數據。也就是出現問題時,的聲音數據,讓我們可以快速的定位出現問題的位置。

簡單的說下播放一首歌曲的流程:(以Android O 為例)

上層創建一個MediaPlayer對象,然後調用NuPlayer框架(播放器),NuPlayer先將當前歌曲的文件信息讀取,采樣率,比特率,等之類的東西。然後開始調用audio decoder (音頻解碼器)  將解碼出來的PCM數據傳給AudioTrack,  Audiotrack 會創建一個Track,(每一個播放都會創建一個屬於自己的track,不用了就銷毀,最多可以同時創建32個),經過AudioFlinger重采樣之後,送到HAL層,HAL層在經過一些混音,降噪之類的處理,將聲音送到Codec,然後送給硬體輸出,進行播放。

這個是一個大概的播放流程,如果我們在播放過程中遇到了一些問題,比如說是fwk層的問題,我們就在AudioTrack與AudioFlinger之間尋問題的原因。

比如說,播放無聲,我們需要看AudioPolicyManager中的一些策略是不是將當前的track給mute了。或者是一些其他的原因等。

這里只是簡單的介紹下Audio,Audio算是一個較為復雜的模塊,還需要好好的研究。

⑵ Android緋葷粺涓鐨勯煶瑙嗛戞敮鎸佹湁鍝浜


Android緋葷粺涓瀹屽杽鐨勯煶瑙嗛戞敮鎸
鑷浠嶢ndroid緋葷粺闂涓栦互鏉ワ紝瀹冨凡緇忔垚涓轟簡縐誨姩璁懼囬嗗煙鏈涓烘垚鍔熺殑鎿嶄綔緋葷粺涔嬩竴銆傝ョ郴緇熷叿鏈夊己澶х殑澶氬獟浣撳勭悊鍔熻兘錛屽備赴瀵岀殑闊抽戝拰瑙嗛戞敮鎸侊紝鍙璁╁紑鍙戣呰交鏉懼壋寤哄嚭鍔熻兘涓板瘜鐨勯煶瑙嗛戝簲鐢ㄧ▼搴忋傛湰鏂囧皢鎺㈣ˋndroid緋葷粺涓浣跨敤鐨勫父瑙侀煶瑙嗛戞嗘灦鍜孉PI鎺ュ彛銆
1.OpenMAX緙栬В鐮佸櫒錛
OpenMAX緙栬В鐮佸櫒鏄涓縐嶅彲鐢ㄤ簬Android璁懼囦腑鐨勭‖浠跺姞閫熸妧鏈銆傝ユ妧鏈鍙浠ュ府鍔╁湪璁懼囦笂鎾鏀鵑珮娓呮垨嫻佸獟浣撹嗛戞椂鍑忓皯濯掍綋鏂囦歡鐨勫崰鐢ㄧ┖闂淬備綔涓轟竴縐嶅紑鏀炬爣鍑嗭紝OpenMAX鏀鎸佷粠搴旂敤紼嬪簭鍒扮‖浠剁殑鍏ㄩ潰瑙e喅鏂規堛傚湪Android緋葷粺涓錛孫penMAX鏄鐢辯‖浠跺巶鍟嗘彁渚涙敮鎸侊紝騫朵笖瀹冨厑璁鎬笉鍚岀殑紜浠跺拰杞浠剁粍鍚堝簱鐩鎬簰鍗忎綔銆
2.Medistore錛
Mediastore鏄疉ndroid緋葷粺鐨勪竴涓澶氬獟浣撲腑闂村眰銆傚畠浣跨敤鎴峰彲浠ュ揩閫熸柟渚垮湴鑾峰彇銆佸瓨鍌ㄥ拰澶勭悊縐誨姩璁懼囩殑澶氬獟浣撴暟鎹銆傚畠鏀鎸佽稿氭牸寮忓侻P3銆丳NG絳夛紝鑰屼笖瀹冨彲浠ラ氳繃URI鐨勬柟寮忚塊棶鍒扮郴緇熺殑澶氬獟浣撴暟鎹銆傚逛簬寮鍙戜漢鍛樻潵璇達紝Mediastore榪樻彁渚涗簡璁稿氭帴鍙e拰綾伙紝鍙甯鍔╀粬浠綆$悊澶氬獟浣撴暟鎹銆
3.MediaPlayer錛
MediaPlayer鏄疉ndroid緋葷粺涓鏈甯哥敤鐨勫氬獟浣撴挱鏀懼櫒銆傚畠鑳藉熶互嫻佺殑鏂瑰紡澶勭悊澶氱嶉煶棰戝拰瑙嗛戞牸寮忥紝濡侻P3銆乄AV絳夐煶棰戞牸寮忥紝浠ュ強MP4銆丠.264絳夎嗛戞牸寮忋侻ediaPlayer榪樺彲浠ヤ笌SurfaceView鍗忓悓宸ヤ綔錛屼互渚挎洿鍔犵伒媧誨湴鎺у埗瑙嗛戠殑鎾鏀俱傚湪寮鍙戣繃紼嬩腑錛屽紑鍙戜漢鍛樺彲浠ヤ嬌鐢∕ediaPlayer綾葷殑璁稿氭柟娉曞拰灞炴ф潵鎺у埗闊抽戝拰瑙嗛戠殑鎾鏀俱佹殏鍋滃拰鍋滄㈢瓑鍔熻兘銆
4.AudioTrack錛
AudioTrack鏄涓涓鍦ˋndroid緋葷粺涓婂勭悊闊抽戞暟鎹鐨勭被銆傚畠鏀鎸佷互鏁版嵁緙撳瓨鏂瑰紡鎾鏀鵑煶棰戣В鐮佹暟鎹錛屽苟鍏佽稿紑鍙戜漢鍛橀氳繃璁稿氭柟娉曞拰灞炴ф潵鎺у埗闊抽戞挱鏀俱侫udioTrack鏈甯哥敤浜庨煶棰戞祦浼犺緭鍜岄煶棰戞枃浠舵挱鏀撅紝渚嬪侻P3鎴朩AV鏂囦歡銆
鎬諱箣錛孉ndroid緋葷粺鐨勯煶瑙嗛戝姛鑳藉湪縐誨姩璁懼囦腑宸茬粡寰楀埌浜嗗箍娉涚殑搴旂敤銆傞氳繃瀵逛笉鍚岀殑API鎺ュ彛鍜屾嗘灦鐨勪簡瑙o紝寮鍙戜漢鍛樺彲浠ヨ交鏉懼壋寤洪珮璐ㄩ噺鐨勯煶瑙嗛戝簲鐢ㄧ▼搴忋

⑶ Android音頻播放

最近需要在Android的客戶端中使用PCM聲音播放和錄制,簡單學習了一下。有不正確的地方還請指出。

首先有幾個概念需要了解一下:采樣頻率、聲道數、采樣位數。

采樣頻率一般是sample rate, 代表的是數字化音頻時每秒采樣的次數。常見的有44.1KHz(CD品質)、48KHz等。

這個很好理解,單聲道Mono就是聲音從一個方向傳出來;雙聲道Stereo也叫立體聲,聲音是從兩個方向傳來。通常的流行音樂中,仔細聽能發現每個聲道可能側重不同的樂曲聲部,比如左聲道吉他,右聲道鋼琴,人聲似乎兩個聲道都有,聽起來就像站在中間一樣。(這里沒有考證,隨便舉例)

每一個采樣都是一個數據點,采樣位數是指這個數據點使用了幾位來記錄。AudioTrack類只支持8位和16位的PCM音頻。8位就是2的8次方,即256個值;而16位則是2的16次方,有65536個值。

這個在音頻的編解碼中還是比較常用的。在PCM格式中,1秒鍾音頻的數據大小是SampleRate×Channel×Bit/8,單位是byte位元組。由於PCM本身沒有音頻幀的概念,所以通過這個公式就能計算出任意時長音頻的大小,或者得到任意大小音頻的時長。如果規定1個音頻幀是「每個聲道256個采樣」,雙聲道下就是512個采樣,那麼1幀的數據量就是256×Channel×Bit/8,同理可以推斷出1秒鍾有多少音頻幀等等。音頻幀的概念在各種編解碼中各有不同,但計算公式大同小異,這里不展開。

Android中音頻的播放使用的是AudioTrack類,具體用法非常簡單。
首先設置buffer大小。AudioTrack播放時需要先寫入buffer,如果這個buffer沒有寫滿,那麼這部分是不會播放的。所以buffer不能設置太小,這樣會導致播放不連貫;而buffer也不能設置太小,這樣不間斷寫入會消耗許多CPU資源。AudioTrack自帶了getMinBufferSize方法可以給出一個最小buffer,一般用這個值就可以。getMinBufferSize方法三個參數分別是sample rate、channel和bit。

設置完buffer size就可以實例化一個AudioTrack。其中第一個參數streamType是指不同的音頻流類型,包括STREAM_MUSIC、STREAM_ALARM、STREAM_VOICE_CALL、STREAM_RING等,是Android對不同音頻的分類。中間三個參數很好理解,第四個是buffer size,剛剛計算出來了。最後一個參數mode有兩種:MODE_STREAM和MODE_STATIC。前者是以流形式播放,後者則是一次性全部寫入然後播放。

調用實例的play()方法就可以開始播放了。不過播放得要有數據吧?要填寫數據就要用到write()方法。write方法中第一個參數是一個byte[]類型,是要寫入的數據源,可以是從文件流中讀取出來的;第二個參數offset是初始位移,即從source的哪個位置開始;第三個參數則是輸入長度。

當write方法寫滿一個AudioTrack的buffer時,就會有聲音播放出來了。
當播放完成後記得要把AudioTrack停止並釋放。

⑷ Android的MediaRecorder怎麼顯示音頻記錄的時間期限

解決卜困枯方法 :
在記錄開始的 System.currentTimeMillis(); 方法中設置 start_time 方法。
然後使用 Runnable 可型洞以執行一個循環,直到停止記錄。

final Handler handler = new Handler();
Runnable update_runnable = new Runnable() {
public void run() {
updateTextView();
}
};
Then with the updateTextView() you'd do something like this:

long ration = (int) ((System.currentTimeMillis() - start_time) / 1000);
// ... set TextView with ration value
handler.postDelayed(update_runnable, 1000); /尺羨

熱點內容
linux工程師證書 發布:2024-09-22 20:07:37 瀏覽:412
如何快速調整安卓手機桌面 發布:2024-09-22 20:06:26 瀏覽:683
GDC伺服器怎麼做IP 發布:2024-09-22 19:44:54 瀏覽:466
c語言longlongprintf 發布:2024-09-22 19:16:48 瀏覽:13
oracleraclinux 發布:2024-09-22 19:03:54 瀏覽:51
我的世界伺服器v指令是什麼 發布:2024-09-22 19:03:52 瀏覽:431
UE編譯器網盤下載 發布:2024-09-22 19:01:48 瀏覽:827
linux下遠程 發布:2024-09-22 18:56:10 瀏覽:234
python類單例 發布:2024-09-22 18:45:52 瀏覽:278
打游戲要看手機的什麼配置 發布:2024-09-22 18:40:06 瀏覽:974