導航:首頁 > 操作系統 > androidaudio的播放

androidaudio的播放

發布時間:2023-09-10 16:03:55

A. android音視頻【十二】使用OpenSLES和AudioTrack進行播放PCM

本節我們學習下如何播放pcm數據,在Android中有兩種方法:一種是使用java層的 AudioTrack 方法,一種是使用底層的 OpenSLES 直接在 jni 層調用系統的 OpenSLES的c方法 實現。

兩種使用場景不一樣:
AudioTrack 一般用於 比如本地播放一個pcm文件/流,又或者播放解碼後的音頻的pcm流,API較簡單。
OpenSLES 一般用於一些播放器中開發中,比如音頻/視頻播放器,聲音/音頻的播放採用的OpenSLES,一是播放器一般是c/c++實現,便於直接在c層調用OpenSLES的API,二也是如果用AudioTrack進行播放,務必會帶來java和jni層的反射調用的開銷,API較復雜。

可以根據業務自行決定來進行選擇。

AudioTrack的方式使用較簡單,直接在java層。

指定采樣率,采樣位數,聲道數進行創建。

其中44100是采樣率, AudioFormat.CHANNEL_OUT_STEREO 為雙聲道,還有 CHANNEL_OUT_MONO 單聲道。 AudioFormat.ENCODING_PCM_16BIT 為采樣位數16位,還有 ENCODING_PCM_8BIT 8位。 minBufferSize 是播放器緩沖的大小,也是根據采樣率和采樣位數,聲道數 進行獲取,只有滿足最小的buffer才去操作底層進程播放。

最後一個參數mode。可以指定的值有 AudioTrack.MODE_STREAM 和 AudioTrack.MODE_STATIC 。

MODE_STREAM 適用於大多數的場景,比如動態的處理audio buffer,或者播放很長的音頻文件,它是將audio buffers從java層傳遞到native層。音頻播放時音頻數據從Java流式傳輸到native層的創建模式。

MODE_STATIC 適用場景,比如播放很短的音頻,它是一次性將全部的音頻資源從java傳遞到native層。音頻數據在音頻開始播放前僅從Java傳輸到native層的創建模式。

是的,就這么一個方法。注意此方法是同步方法,是個耗時方法,一般是開啟一個線程循環調用 write 方法進行寫入。
注意在調用 write 方法前需要調用 audioTrack.play() 方法開始播放。

因為是pcm裸數據,無法像mediaplayer一樣提供了API。所以需要自己處理下。可以利用 getPlaybackHeadPosition 方法。

getPlaybackHeadPosition() 的意思是返回以幀為單位表示的播放頭位置
getPlaybackRate() 的意思是返回以Hz為單位返回當前播放采樣率。

所以當前播放時間可以通過如下方式獲取

OpenSLES:(Open Sound Library for Embedded Systems).
OpenSLES是跨平台是針對嵌入式系統精心優化的硬體音頻加速API。使用OpenSLES進行音頻播放的好處是可以不依賴第三方。比如一些音頻或者視頻播放器中都是用OpenSLES進行播放解碼後的pcm的,這樣免去了和java層的交互。

在Android中使用OpenSLES首先需要把Android 系統提供的so鏈接到外面自己的so。在CMakeLists.txt腳本中添加鏈接庫OpenSLES。庫的名字可以在 類似如下目錄中

需要去掉lib

然後導入頭文件即可使用了OpenSLES提供的底層方法了。

創建&使用的步驟大致分為:

一個 SLObjectItf 裡面可能包含了多個Interface,獲取Interface通過 GetInterface 方法,而 GetInterface 方法的地2個參數 SLInterfaceID 參數來指定到的需要獲取Object裡面的那個Interface。比如通過指定 SL_IID_ENGINE 的類型來獲取 SLEngineItf 。我們可以通過 SLEngineItf 去創建各種Object,例如播放器、錄音器、混音器的Object,然後在用這些Object去獲取各種Interface去實現各種功能。

如上所說,SLEngineItf可以創建混音器的Object。

在創建播放器前需要創建音頻的配置信息(比如采樣率,聲道數,每個采樣的位數等)

開始播放後會不斷的回調這個 pcmBufferCallBack 函數將音頻數據壓入隊列
(*pcmBufferQueue)->RegisterCallback(pcmBufferQueue, pcmBufferCallBack, this);

如果想要暫停播放參數直接設置為SL_PLAYSTATE_PAUSED,若暫停後繼續播放設置參數為SL_PLAYSTATE_PLAYING即可。若想要停止播放參數設置為SL_PLAYSTATE_STOPPED即可。

首先獲取播放器的用於控制音量的介面SLVolumeItf pcmVolumePlay

然後動態設置

首先也是獲取播放器的用於控制音量的介面SLMuteSoloItf pcmMutePlay

然後動態設置

看起來控制還是蠻簡單的哈。先熟悉這么多,OpenSLES還是蠻強大的。

https://github.com/ta893115871/PCMPlay

B. Android播放簡短音頻-SoulPool

前言

最近新接觸的項目中有一個業務功能是語音播報,所以有接觸到了SoulPool這個類,寫個文章記錄一下~

如果項目業務功能中需要播放簡短的音頻的話,可以使用SoundPool 。SoundPool 是 Android 提供的一個API類,用來播放簡短音頻的,使用起來簡單並且功能強大。

SoundPool 除了可以完成音頻的播放、暫停、恢復及停止的操作外,還可以調節左右聲道的音量值、調整播放的語速、設置播放的優先順序以及播放的次數等等。

創建SoulPool

SoundPool 的創建方式在Android 5.0 以前是直接使用SoundPool 的構建方法即可,在Android5.0之後,則是使用Builder模式來創建。為了更好的兼容性,我們可以判斷一下api版本進行對應的創建。

Android5.0之前SoundPool 的構造函數有三個參數分別是maxStreams、streamType和srcQuality。

maxStreams:同時播放流的最大數量,當播放的流大於此設置值時,則會選擇性停止優先順序較低的流;

streamType:流類型,例如STREAM_MUSIC、STREAM_ALARM、STREAM_NOTIFICATION等;

srcQuality:采樣率轉換器質量,很少用得上,默認設置0即可;

Android5.0 之後,使用Builder模式進行構造,可以設置多個參數。我這里放兩張源碼截圖,如果需要詳細了解的,可以自己點進去追蹤一下~

SoundPool.Builder中setMaxStreams和之前Android5.0SoundPool的構造函數maxStreams參數相同。SoundPool.Builder中setAudioAttributes用來設置audio 屬性,此值要麼不設,要麼設置不為null的值,否則會導致異常產生。

音頻資源的載入與播放

首先我們要進行音頻資源的載入,載入成功之後,才能進行播放。載入音頻,我們可以使用SoulPool實例中的load方法。

載入音頻資源時非同步執行的,此過程需要時間,所以我們可以使用SoulPool中的OnLoadCompleteListener介面進行監聽,其中的onLoadComplete方法則是在音頻資源載入完成後調用。

我們還可以通過SoulPool中的unload方法,卸載之前載入過的資源。

其實,只要我們點進去SoulPool類中,就能看見它提供的所有方法了,如上圖。

音頻播放,我們是使用到了SoulPool實例中的play方法,該方法要傳比較多的參數,分別是soundID、leftVolume、rightVolume、priority、loop和rate,它們分別代表的意思是:

soundID:是SoulPool載入資源load方法返回的值,指向某個已載入的音頻資源;

leftVolume和rightVolume:分別代表左聲道和右聲道的值,設置范圍在0f ~ 1f;

priority:則是流的優先順序;

loop:是循環播放的次數, 例如-1是表示無限循環;

rate:則是播放的速率 ,1是正常速率,如果設置2則表示2倍速率;

play方法返回的streamID,若返回0則播放失敗,其它值都代表播放成功。

圖中方法還有pause、resume、stop分別代表暫停音播放、恢復音頻播放和停止音頻播放。SoulPool提供的方法,源碼中都有,這里就不一一細說了。記得!一定要釋放資源(release)

注意事項

1.SoulPool並不是什麼格式的音頻資源都支持的,MP3這些常見的格式當然是支持的,如果有別的格式的音頻可以自己測試一下;

2.SoulPool是Android為了播放簡短音頻提供的api,所以盡量不要播放時間過長的音頻;

3.設置播放流的優先順序的問題,如果同時播放的活動流的數目超過設置的maxStreams時,會根據優先順序來停止優先順序較低的流;如果有多個具有相同低優先順序的流,它將選擇要停止的最舊流,並且該流不再有效;如果要播放的流的優先順序最低,則會播放失敗。

4.載入音頻資源的數量限制也注意一下,別載入過多。

                                2021年9月15日程序猿小鍾帶著【播放簡短音頻類-SoulPool】到此一游~

C. android 5.0怎麼設置音樂從聽筒播放

5.0 之前 可以用AudioManager.setMode來設置phone state 來達到切換聽筒的目的,但是5.0之後非系統應用沒有這個許可權了。發現微信依然可以切換,研究了下底層設備切換發現是如下操作的:
1.播放音頻流類型要設置為AudioManager.STREAM_VOICE_CALL
2.在播放前調用AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION,AudioSystem.FORCE_NONE);
這個調用需要 在AndroidManifest.xml中添加 android.permission.MODIFY_AUDIO_SETTINGS 許可權
並且AudioSystem這個類是隱藏類,在Android 公開API中沒有,所以需要用反射調用,或者自己編譯出一個framework.jar包,放到工程里,不過這樣有可能兼容性不是很好。

閱讀全文

與androidaudio的播放相關的資料

熱點內容
怎麼查伺服器同行fc號 瀏覽:991
什麼伺服器雲鳥最便宜 瀏覽:214
vs編譯器反匯編 瀏覽:562
程序員直播做項目創業 瀏覽:396
linux下samba配置 瀏覽:795
程序員面試銀行崗位會有編制嗎 瀏覽:412
ex表怎麼加密碼保護 瀏覽:170
小孩上編程課用哪款好 瀏覽:556
如何製作伺服器商店 瀏覽:732
壓縮氣管閥門 瀏覽:464
pdf推文 瀏覽:358
69程序員 瀏覽:581
阿里雲伺服器鏡像如何遷移到騰訊 瀏覽:989
安卓如何顯示日期在狀態欄 瀏覽:805
cadsplt這個命令用不了 瀏覽:467
安卓誇克怎麼取消監管 瀏覽:664
pdf怎麼裁剪圖片 瀏覽:440
黑上宏命令 瀏覽:646
mac解壓壓縮包有密碼 瀏覽:708
命令與征服知乎 瀏覽:564