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

android音頻系統

發布時間: 2022-11-22 11:10:34

❶ android2.3採用alsa作為音頻系統,在asound.conf中的揚聲器音量設置問題。

這個我也碰到過,是常規問題,原因在於音頻系統不兼容,如果您的設置裡面有「db分位噪比」選項,可以將其數值加大,一般到210即可。如果沒有此選項,那您只好換個音頻系統了,我就換了,以後再也沒有出現類似的問題

❷ Android Audio System 之一:AudioTrack如何與AudioFlinger交換

引子Android Framework的音頻子系統中,每一個音頻流對應著一個AudioTrack類的一個實例,每個AudioTrack會在創建時注冊到 AudioFlinger中,由AudioFlinger把所有的AudioTrack進行混合(Mixer),然後輸送到AudioHardware中 進行播放,目前Android的Froyo版本設定了同時最多可以創建32個音頻流,也就是說,Mixer最多會同時處理32個AudioTrack的數 據流。如何使用AudioTrackAudioTrack的主要代碼位於 frameworks/base/media/libmedia/audiotrack.cpp中。現在先通過一個例子來了解一下如何使用 AudioTrack,ToneGenerator是android中產生電話撥號音和其他音調波形的一個實現,我們就以它為例子:ToneGenerator的初始化函數:bool ToneGenerator::initAudioTrack() { // Open audio track in mono, PCM 16bit//, default sampling rate, default buffer size mpAudioTrack = new AudioTrack(); mpAudioTrack->set(mStreamType, 0, AudioSystem::PCM_16_BIT, AudioSystem::CHANNEL_OUT_MONO, 0, 0, audioCallback, this, 0, 0, mThreadCanCalljava); if (mpAudioTrack->initCheck() != NO_ERROR) { LOGE("AudioTrack->initCheck failed"); goto initAudioTrack_exit; } mpAudioTrack->setVolume(mVolume, mVolume); mState = TONE_INIT; ...... } 可見,創建步驟很簡單,先new一個AudioTrack的實例,然後調用set成員函數完成參數的設置並注冊到AudioFlinger中,然後可以調 用其他諸如設置音量等函數進一步設置音頻參數。其中,一個重要的參數是audioCallback,audioCallback是一個回調函數,負責響應 AudioTrack的通知,例如填充數據、循環播放、播放位置觸發等等。回調函數的寫法通常像這樣:void ToneGenerator::audioCallback(int event, void* user, void *info) { if (event != AudioTrack::EVENT_MORE_DATA) return; AudioTrack::Buffer *buffer = static_cast<AudioTrack::Buffer *>(info); ToneGenerator *lpToneGen = static_cast<ToneGenerator *>(user); short *lpOut = buffer->i16; unsigned int lNumSmp = buffer->size/sizeof(short); const ToneDescriptor *lpToneDesc = lpToneGen->mpToneDesc; if (buffer->size == 0) return; // Clear output buffer: WaveGenerator accumulates into lpOut buffer memset(lpOut, 0, buffer->size); ...... // 以下是產生音調數據的代碼,略.... } 該函數首先判斷事件的類型是否是EVENT_MORE_DATA,如果是,則後續的代碼會填充相應的音頻數據後返回,當然你可以處理其他事件,以下是可用的事件類型:enum event_type { EVENT_MORE_DATA = 0,// Request to write more data to PCM buffer. EVENT_UNDERRUN = 1,// PCM buffer underrun occured. EVENT_LOOP_END = 2,// Sample loop end was reached; playback restarted from loop start if loop count was not 0. EVENT_MARKER = 3,// Playback head is at the specified marker position (See setMarkerPosition()). EVENT_NEW_POS = 4,// Playback head is at a new position (See setPositionUpdatePeriod()). EVENT_BUFFER_END = 5// Playback head is at the end of the buffer. }; 開始播放:mpAudioTrack->start(); 停止播放:mpAudioTrack->stop(); 只要簡單地調用成員函數start()和stop()即可。AudioTrack和AudioFlinger的通信機制通常,AudioTrack和AudioFlinger並不在同一個進程中,它們通過android中的binder機制建立聯系。AudioFlinger是android中的一個service,在android啟動時就已經被載入。下面這張圖展示了他們兩個的關系:圖一AudioTrack和AudioFlinger的關系我們可以這樣理解這張圖的含義:audio_track_cblk_t實現了一個環形FIFO;AudioTrack是FIFO的數據生產者;AudioFlinger是FIFO的數據消費者。建立聯系的過程下面的序列圖展示了AudioTrack和AudioFlinger建立聯系的過程:圖二AudioTrack和AudioFlinger建立聯系解釋一下過程:Framework或者Java層通過JNI,new AudioTrack();根據StreamType等參數,通過一系列的調用getOutput();如有必要,AudioFlinger根據StreamType打開不同硬體設備;AudioFlinger為該輸出設備創建混音線程: MixerThread(),並把該線程的id作為getOutput()的返回值返回給AudioTrack;AudioTrack通過binder機制調用AudioFlinger的createTrack();AudioFlinger注冊該AudioTrack到MixerThread中;AudioFlinger創建一個用於控制的TrackHandle,並以IAudioTrack這一介面作為createTrack()的返回值;AudioTrack通過IAudioTrack介面,得到在AudioFlinger中創建的FIFO(audio_track_cblk_t);AudioTrack創建自己的監控線程:AudioTrackThread;自此,AudioTrack建立了和AudioFlinger的全部聯系工作,接下來,AudioTrack可以:通過IAudioTrack介面控制該音軌的狀態,例如start,stop,pause等等;通過對FIFO的寫入,實現連續的音頻播放;監控線程監控事件的發生,並通過audioCallback回調函數與用戶程序進行交互;FIFO的管理 audio_track_cblk_taudio_track_cblk_t這個結構是FIFO實現的關鍵,該結構是在createTrack的時候,由AudioFlinger申請相 應的內存,然後通過IMemory介面返回AudioTrack的,這樣AudioTrack和AudioFlinger管理著同一個 audio_track_cblk_t,通過它實現了環形FIFO,AudioTrack向FIFO中寫入音頻數據,AudioFlinger從FIFO 中讀取音頻數據,經Mixer後送給AudioHardware進行播放。audio_track_cblk_t的主要數據成員: user -- AudioTrack當前的寫位置的偏移 userBase -- AudioTrack寫偏移的基準位置,結合user的值方可確定真實的FIFO地址指針 server -- AudioFlinger當前的讀位置的偏移 serverBase -- AudioFlinger讀偏移的基準位置,結合server的值方可確定真實的FIFO地址指針 frameCount -- FIFO的大小,以音頻數據的幀為單位,16bit的音頻每幀的大小是2位元組 buffers -- 指向FIFO的起始地址 out -- 音頻流的方向,對於AudioTrack,out=1,對於AudioRecord,out=0audio_track_cblk_t的主要成員函數:framesAvailable_l()和framesAvailable()用於獲取FIFO中可寫的空閑空間的大小,只是加鎖和不加鎖的區別。uint32_t audio_track_cblk_t::framesAvailable_l() { uint32_t u = this->user; uint32_t s = this->server; if (out) { uint32_t limit = (s < loopStart) ? s : loopStart; return limit + frameCount - u; } else { return frameCount + u - s; } } framesReady()用於獲取FIFO中可讀取的空間大小。uint32_t audio_track_cblk_t::framesReady() { uint32_t u = this->user; uint32_t s = this->server; if (out) { if (u < loopEnd) { return u - s; } else { Mutex::Autolock _l(lock); if (loopCount >= 0) { return (loopEnd - loopStart)*loopCount + u - s; } else { return UINT_MAX; } } } else { return s - u; } } 我們看看下面的示意圖: _____________________________________________ ^ ^ ^ ^ buffer_start server(s) user(u) buffer_end 很明顯,frameReady = u - s,frameAvalible = frameCount - frameReady = frameCount - u + s 可能有人會問,應為這是一個環形的buffer,一旦user越過了buffer_end以後,應該會發生下面的情況: _____________________________________________ ^ ^ ^ ^ buffer_start user(u) server(s) buffer_end這時候u在s的前面,用上面的公式計算就會錯誤,但是android使用了一些技巧,保證了上述公式一直成立。我們先看完下面三個函數的代碼再分析:uint32_t audio_track_cblk_t::stepUser(uint32_t frameCount) { uint32_t u = this->user; u += frameCount; ...... if (u >= userBase + this->frameCount) { userBase += this->frameCount; } this->user = u; ...... return u; } bool audio_track_cblk_t::stepServer(uint32_t frameCount) { // the code below simulates lock-with-timeout // we MUST do this to protect the AudioFlinger server // as this lock is shared with the client. status_t err; err = lock.tryLock(); if (err == -EBUSY) { // just wait a bit usleep(1000); err = lock.tryLock(); } if (err != NO_ERROR) { // probably, the client just died. return false; } uint32_t s = this->server; s += frameCount; // 省略部分代碼 // ...... if (s >= serverBase + this->frameCount) { serverBase += this->frameCount; } this->server = s; cv.signal(); lock.unlock(); return true; } void* audio_track_cblk_t::buffer(uint32_t offset) const { return (int8_t *)this->buffers + (offset - userBase) * this->frameSize; } stepUser()和stepServer的作用是調整當前偏移的位置,可以看到,他們僅僅是把成員變數user或server的值加上需要移動 的數量,user和server的值並不考慮FIFO的邊界問題,隨著數據的不停寫入和讀出,user和server的值不斷增加,只要處理得 當,user總是出現在server的後面,因此frameAvalible()和frameReady()中的演算法才會一直成立。根據這種算 法,user和server的值都可能大於FIFO的大小:framCount,那麼,如何確定真正的寫指針的位置呢?這里需要用到userBase這一 成員變數,在stepUser()中,每當user的值越過(userBase+frameCount),userBase就會增加 frameCount,這樣,映射到FIFO中的偏移總是可以通過(user-userBase)獲得。因此,獲得當前FIFO的寫地址指針可以通過成員 函數buffer()返回:p = mClbk->buffer(mclbk->user);在AudioTrack中,封裝了兩個函數:obtainBuffer()和releaseBuffer()操作 FIFO,obtainBuffer()獲得當前可寫的數量和寫指針的位置,releaseBuffer()則在寫入數據後被調用,它其實就是簡單地調用 stepUser()來調整偏移的位置。IMemory介面在createTrack的過程中,AudioFlinger會根據傳入的frameCount參數,申請一塊內存,AudioTrack可以通過 IAudioTrack介面的getCblk()函數獲得指向該內存塊的IMemory介面,然後AudioTrack通過該IMemory介面的 pointer()函數獲得指向該內存塊的指針,這塊內存的開始部分就是audio_track_cblk_t結構,緊接著是大小為frameSize的 FIFO內存。IMemory->pointer() ---->|_______________________________________________________ |__audio_track_cblk_t__|_______buffer of FIFO(size==frameCount)____|看看AudioTrack的createTrack()的代碼就明白了:sp<IAudioTrack> track = audioFlinger->createTrack(getpid(), streamType, sampleRate, format, channelCount, frameCount, ((uint16_t)flags) << 16, sharedBuffer, output, &status); // 得到IMemory介面 sp<IMemory> cblk = track->getCblk(); mAudioTrack.clear(); mAudioTrack = track; mCblkMemory.clear(); mCblkMemory = cblk; // 得到audio_track_cblk_t結構 mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer()); // 該FIFO用於輸出 mCblk->out = 1; // Update buffer size in case it has been limited by AudioFlinger ring track creation mFrameCount = mCblk->frameCount; if (sharedBuffer == 0) { // 給FIFO的起始地址賦值 mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t); } else { .......... } (DroidPhone)

❸ Android音頻底層調試-基於tinyalsa

因為Android中默認並沒有使用標准alsa,而是使用的是tinyalsa。所以就算基於命令行的測試也要使用libtinyalsa。Android系統在上層Audio千變萬化的時候,能夠能這些個工具實時查看到,比方音頻通道的切換等等。

編譯完後會產生tinyplay、tinymix、tinycap等工具。

tinymix用法:

相應解釋:

Playback Path:

例:將輸出切換到揚聲器

關於tinymix小結:

通過觀察發現,Android系統的聲音音量的調節並沒有直接使用tinyalsa,而基於上層軟體實現。由於不管上層音量怎麼改變,這里看到的都是24(以我使用的設備為例)。

通道的切換是真正使用了tinyalsa,當通過不同通道播放音樂的時候能夠實時觀察到通道的切換。在某個站點上看到Android在沒有聲音播放的3秒後會關閉alsa,這里也得到了證實,我曾經覺得Android系統會永久佔用音頻設備。

當通過藍牙播放音樂的時候,已經不經過alsa了,tinymix查看到都處理關閉狀態。由於Android4.2的藍牙協議所有在用戶層實現了,直接走uart通道。

一般播放1khz 0db正弦波,然後在codec輸出端示波器簡單測量是否失真,雜音,然後再使用音頻分析儀測試指標。

tinyalsa源碼
原文: https://www.cnblogs.com/yxwkf/p/5344068.html

安卓系統為什麼音質不好

Android 基於Linux,我們先來了解一下Linux的特點。Linux使用ALSA作為其音頻架構,其全稱Advanced Linux Sound Architecture,即高級Linux聲音架構的意思,在2.6核心之後,ALSA成為了Linux系統默認的音頻子架構。取代了之前的OSS[Open Sound System,開放式聲音系統]。

ALSA並不太好理解,它首先是一個驅動庫,包含了大量的音效卡設備的開源驅動,並提供了核心層API與ALSA庫通信,而ALSA庫則是應用程序訪問和操控音頻硬體的中間層,這個中間層有標准介面,開發者可以無須考慮硬體差異性進行開發,它對提升開發效率是大有幫助的。ALSA可以向下兼容OSS,因為OSS已經被淘汰,其兼容的工作模式不再討論。

這個體系被繼承到了Android當中。在Android2.2[含2,2]之前,系統文件夾中能找到一個LibAudioALSA.so的文件,這就是ALSA庫文件,其他應用程序調用它,與音效卡設備進行指令和數據通信。Android音頻架構與Linux的並無本質區別。

在桌面版本的Linux當中,為了兼容各類音效卡,Linux也設置了一個SRC[Sample Rate Converter,采樣頻率轉換]的環節,當當前采樣率低於48kHz時強制SRC到48kHz輸出。這個SRC環節位於ALSA的插件模塊中的混音器部分。Android針對這個進行了改進。
什麼是SRC?SRC即Sample Rate Converter,中文意思為采樣頻率轉換。它被音效卡愛好者所關注,大部分發燒友視SRC為音質殺手。

Android增加了一個AudioFinger,這個可以簡單的理解為Android的ALSA音頻子系統的標准化的插件模塊,它包含了AudioMixer[混音器]、AudioResampler[重采樣]等子模塊,AudioResampler即我們理解的SRC,Android換了一個新名稱而已。針對SRC,Android做了改進,但改進並不是以去除SRC為目的,而是修改了默認的輸出頻率,Android的SRC目標采樣率為44.1kHz,非該值的采樣率都將SRC處理。例如播放48kHz采樣率的信號,輸出的最終是44.1kHz,這對音質將產生負面影響。

ALSA是一個針對Linux 桌面版本設計的音頻架構,它實際上是不適合智能終端設備的,起碼裡面大量的開源驅動代碼是可以去除的,對與Android來說,這些都是廢代碼。從Android2.3起,啟用了一個新的音頻架構。它放棄了一直使用的ALSA架構,因此系統文件夾中,也不再有LibAudioALSA.so這個文件。

Android2.3起,架構已經做了修改,在針對內部代碼進行了優化,去除了冗餘代碼,理論上讓系統能變得更加高效,可以將新架構理解為一個精簡的或者為智能終端設備定製的ALSA架構。遺憾的是,它同樣存在SRC嚴重劣化的問題,通過測試可以證明。
Android 3.0專門為平板電腦設計,影音體驗變得更加重要了,是不是新系統在音質方面會有新的的進步呢,測試結果依然是令人失望的。

Android系統將采樣率同一為44.1kHz輸出,這造成了諸多限制,它將無法實現96kHz、192kHz高清音頻節目的良好回放,大量視頻節目源自DVD或者藍光碟,其採用率多為48kHz,Android設備在回放這些視頻節目時,音質也將大打折扣。

理論上軟體SRC可以通過更換演算法來實現音質提升,但卻不太現實,智能終端所採用的CPU多為ARM,ARM晶元的浮點運算力有限,而SRC需要大量的浮點運算的資源,即便有了高質量的SRC演算法,其運算也是以犧牲設備性能和耗電量為代價的,實用性差。

從Android的音頻架構及流程分析,可以認為,播放44.1kHz采樣率的音樂節目時,不會引發SRC,音質因此可以獲得保證,理論上確實如此。但它同樣存在問題,不管是之前的ALSA架構還是Android2.3之後改良的架構,其驅動庫都位於核心層,也就意味著音頻設備廠商、用戶無法象PC平台那樣安裝驅動來改善音質。實際測試也表明,Android設備音質普遍偏差,Soomal有大量測試可以證明。

我們再把目光投向iOS,iOS非常封閉,我們甚至無法獲知其架構的具體構成,但iOS設備不存在硬體設備多樣性的問題,因此要實現更好音質也會更加簡單。iOS可以實現針對性的開發和改良,以實現更好的音質。實際情況也是如此,目前為止,還沒有一款Android設備的音質可以媲美任意一款iOS設備,這種差距,我們認為不是來自硬體,而是操作系統。

Android音頻架構的局限性也使得其難以成為優質的影音平台,如果你希望設計一款基於Android的高清影音播放器,那麼首先需要做的不是設計硬體,而是去修改現有架構的不足,或者乾脆設計一個專用的架構來取代Android的通用架構。從源代碼分析,Android和原生的Linux底層能支持各種采樣率,開源也使得其具有改造基礎,因此,在技術實力強勁的公司手裡,Android也可以烏雞變鳳凰。

❺ android5.0系統音頻是否還有src的問題

一直以來,Android系統由於底層語言的問題,在音頻播放上存在一個漏洞,即48khz采樣率轉換為44.1khz會被劣質SRC。這種被劣質SRC的問題,使得音頻信號在安卓設備里受到了扭曲和損耗,產生大量噪波,立體聲播放層次等這些指標全面受損。而用戶需求較多的高品質音樂母生帶、高清視頻、游戲等的音頻都是高於44.1khz的采樣率;因此有很多用戶不厭其煩抱怨安卓機器的音質失真和受損問題。
通過一段標准音頻理論狀態下的光譜圖,我們可以發現正常安卓機型在播放48khz音頻時,光譜圖可謂慘不忍睹。主信號周圍出現了巨量的噪波,主信號基本難以分辨,因此難免會出現聲道串聲,雜音,變調等問題。
近期智能手機廠商vivo發布了其自主研發的音頻技術VRS。據了解,vivo的VRS技術聲稱完全解決了上述困擾安卓系統音頻播放的夢魘,並得到了國家專利受理。
而應用了VRS音頻技術的vivo V1智能手機在播放48khz音頻時,完全不存在任何問題,其主信號的保真度接近於理論完美狀態。雖然信號源質量並不完全代表最後的聽感,但我們也知道,有了接近無損的信號源,是能夠取得優秀播放效果的前提。可見,VRS技術的出現,表明vivo智能手機在致力於追求產品完美的音質享受探索又邁上了一個新的高度。

❻ smoothaction為什麼有雜音

smoothaction為什麼有雜音?APP

整個音頻體系的最上層

Framework

MediaPlayer和MediaRecorder、AudioTrack和AudioRecorder,Android系統為控制音頻系統提供了AudioManager、AudioService及AudioSystem類,這些都是framework為便利上層應用開發所設計的

Libraries

系統服務AudioFlinger和AudioPolicyService(比如:ServiceManager、LocationManagerService、ActivityManagerService等等),音頻體系中另一個重要的系統服務是MediaPlayerService

HAL

硬體抽象層是AudioFlinger直接訪問的對象,這說明了兩個問題,一方面AudioFlinger並不直接調用底層的驅動程序;另一方面,AudioFlinger上層(包括和它同一層的MediaPlayerService)的模塊只需要與它進行交互就可以實現音頻相關的功能了。因而我們可以認為AudioFlinger是Android音頻系統中真正的「隔離板」,無論下面如何變化,上層的實現都可以保持兼容。音頻方面的硬體抽象層主要分為兩部分,即AudioFlinger和AudioPolicyService。實際上後者並不是一個真實的設備,只是採用虛擬設備的方式來讓廠商可以方便地定製出自己的策略,抽象層的任務是將AudioFlinger/AudioPolicyService真正地與硬體設備關聯起來

以前Android系統中的Audio系統依賴於ALSA-lib,但後期就變為了tinyalsa,這樣的轉變不應該對上層造成破壞。因而Audio HAL提供了統一的介面來定義它與AudioFlinger/AudioPolicyService之間的通信方式,這就是audio_hw_device、audio_stream_in及audio_stream_out等等存在的目的,這些Struct數據類型內部大多隻是函數指針的定義,是一些「殼」。當AudioFlinger/AudioPolicyService初始化時,它們會去尋找系統中最匹配的實現(這些實現駐留在以audio.primary.*,audio.a2dp.*為名的各種庫中)來填充這些「殼」

理解Android音頻系統的時候分為兩條線索

以庫為線索,比如:AudioPolicyService和AudioFlinger都是在libaudioflinger庫中,而AudioTrack、AudioRecorder等一系列實現則在libmedia庫中

以進程為線索,庫並不代表一個進程,進程則依賴於庫來運行。雖然有的類是在同一個庫中實現的,但並不代表它們會在同一個進程中被調用。比如AudioFlinger和AudioPolicyService都駐留於名為mediaserver的系統進程中,而AudioTrack/AudioRecorder和MediaPlayer/MediaRecorder一樣實際上只是應用進程的一部分,它們通過binder服務來與其它系統進程通信。

❼ 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

❽ android系統支持那些格式的音頻文件

1、H.263:低碼率視頻編碼標准,廣泛應用於視頻會議。

文件格式:

• 3GPP (.3gp)

• MPEG-4 (.mp4)

2、H.264 AVC:和MPEG2和MPEG4 ASP等壓縮技術相比,在同等圖像質量下,採用H.264技術壓縮後的數據量只有MPEG2的1/8,MPEG4的1/3。提供了解決在不穩定網路環境下容易發生的丟包等錯誤的必要工具。從Android3.0+開始支持。在圖像編碼效率上,H.264演算法最為領先,MPEG-4和H.263演算法基本相同。

文件格式:

• 3GPP (.3gp)

• MPEG-4 (.mp4)

• MPEG-TS (.ts, AAC audio only, not seekable, Android 3.0+)

3、MPEG-4 SP:一種以矩形幀作為對象的編碼形式,是從H.263、MPEG1和MPEG2繼承而來的編碼標准。

文件格式:3GPP (.3gp)

4、VP8:Google親媽推出的,但壓縮率比H.264差很多,Android2.3.3+。

文件格式:

• WebM(.webm)

• Matroska (.mkv, Android 4.0+) 註:開源,基於html5標准

❾ Android支持ogg格式的音頻嗎

安卓系統都支持ogg的音頻,包括ogg的音頻格式。

❿ SRC問題可解決 安卓手機音頻分析與測試

【IT168評測】現在一台智能手機繼承了非常多的功能,很多的人都會選擇使用手機來聽歌,手機的音樂播放功能足以取代了以前的MP3播放器的位置。實用手機來聽歌當然是非常方便,但是往往會覺得手機的音質並不是太好,特別是安卓系統的智能手機。


▲智能手機SRC測試

其實安卓智能系統的音頻架構導致了安卓手機的音樂播放質量差的問題,問題根源在於安卓系統在播放采樣頻率高於44.1KHz的音頻是會強制音頻的采樣頻率降低到44.1KHz,在這個過程中直接導致了出現SRC的問題,這是安卓系統的硬傷。關於安卓系統音頻架構可參考《尋找音質變差元兇 聊聊Android音頻架構》

什麼是SRC?SRC即Sample Rate Converter,中文意思為采樣頻率轉換。它被音效卡愛好者所關注,大部分發燒友視SRC為音質殺手。


▲安卓手機普遍存在SRC問題

最近我們收到了一款智能手機針對這個問題提出了他們的解決方案,使得安卓手機在音樂播放音質方面可以領先與其他的安卓智能手機,事實是否如此?下面我們來測試一下。

如何測試?

這款智能手機能夠解決安卓系統SRC問題在眾多手機廠商中算是第一個,我們來對這款手機測試一下,首先是使用20Hz到20KHz的全頻掃描進行測試,之後是進行主觀聽感的測試。


▲測試使用的44.1KHz音頻和48KHz音頻

全頻掃描測試使用2個采樣頻率的wav文件,44.1KHz的音頻和48KHz的音頻,將文件放在手機中進行播放,使用cool edit pro錄音,對錄音進行頻譜分析,入股出現SRC頻頻就會出現雜亂無章的線路。


▲正常沒出SRC的圖像


▲出現SRC時的圖像

第二張圖就是SRC的圖像,現在很多安卓手機都會存在SRC問題,理論上測試結果和第二張圖相似,而步步高vivo智能手機解決了SRC問題測試結果應該要接近第一張圖。


▲測試使用E-MU 0404專業音效卡

由於我們手上沒有專業的測試設備,只能使用電腦進行測試,測試使用E-MU 0404 PC專業音效卡作為輸入音效卡,採用cool edit pro來錄音,由於測試環境並不是十分專業可能會有少量的噪音引入,而圖像也不是十分完美,但也可以反映出問題。

SRC測試

這次測試不僅僅針對某品牌的智能手機,我們也找來了Nexus S和魅族M9進行對比,下面來看一下測試的結果。

44.1KHz采樣頻率音頻掃描:


▲Nexus S測試圖像(點擊放大)


▲魅族M9測試圖像(點擊放大)


▲某品牌安卓測試圖像(點擊放大)

上面的測試圖可以看到安卓系統在44.1KHz的采樣頻率下圖像都是非常干凈的,代表音質是沒有受到任何影響,這是由於安卓音頻架構規定的采樣頻率是44.1KHz,對於大部分的MP3音頻都是在44.1KHz的采樣頻率,對於MP3音頻安卓系統基本上問題不大。

48KHz采樣頻率音頻掃描

48KHz采樣頻率音頻掃描是這次測試的重點,因為安卓系統的音頻架構限制了44.1KHz的采樣頻率,所以高於44.1KHz的采樣頻率就會轉換成44.1KHz,直接導致音質變差,下面來看一下測試結果。


▲Nexus S測試圖像(點擊放大)


▲魅族M9測試圖像(點擊放大)

測試結果慘不忍睹,Nexus S採用安卓4.0系統SRC問題依然存在,圖像出現了很多的交錯的線條,而魅族M9採用安卓2.3系統測試的圖像也說明SRC問題非常嚴重。


▲某品牌安卓智能手機測試圖像(點擊放大)

某品牌安卓智能手機進行48KHz采樣頻率音頻掃描結果要比上面兩款手機要好很多,只在掃描直線上面出現一條很淺色的直線,像對於其他的安卓系統已經是一個非常大的飛躍,對於播放高音質的音頻這款安卓智能手機能更好還原原本音質。

主觀聽感:


▲測試使用的48KHz采樣頻率的MP3

說完理論的東西來點實際的聽感,試用手機聽音樂已經是相當普遍,測試使用2首48KHz采樣頻率的MP3進行測試,試聽某品牌智能手機上和其他智能手機音質有什麼區別。


▲測試使用UE TF10耳機

首先來聽一下一般安卓手機播放48KHz采樣頻率的MP3,測試使用了UE TF10入耳耳機,聽感覺得聲音偏暖,有點朦朧的感覺,而音樂的細節有些地方無法很好的展現,這個問題在幾台安卓手機上同樣遇到,音色都是暖,細節表現不佳。而用耳機聽回前面的20Hz-20KHz掃描是明顯發現問題了,除了掃描信號的聲音外還可以聽到背後有一些跟著掃描信號一起響起的音頻掃描聲音,這就是圖像上交錯的線條,嚴重影響聽感。

再來說一下某品牌智能手機上的聽感,試聽這2隻48KHz采樣頻率的MP3時整體聲音很清晰自然,細節表現非常清晰,沒有過多的音染,音場也比較寬廣,整體上表現非常好。再聽音頻掃描信號,並沒有出現前面的情況,只會聽到音頻掃描信號,非常干凈,沒有任何干擾。

測試總結:


▲SRC問題解決究竟用了什麼技術?

通過這個測試可以看到某品牌的安卓智能手機很好地解決了安卓手機SRC問題,提升了安卓手機音頻播放的音質,雖然由於保密原因現在不方便公布這品牌,而且還不知道採用了什麼技術來解決安卓系統的SRC問題,但是可以肯定的是這個品牌的安卓智能手機是第一個解決安卓系統SRC問題的手機。這個決絕SRC問題的技術也將會會公布,到時我們也會為大家公布這個手機品牌和型號。

熱點內容
伺服器怎麼連接到電腦顯示屏上 發布:2024-05-21 02:38:21 瀏覽:285
織夢安裝資料庫連接失敗 發布:2024-05-21 02:37:45 瀏覽:258
python編程入門經典pdf 發布:2024-05-21 02:31:45 瀏覽:6
arm編譯添加驅動 發布:2024-05-21 02:02:28 瀏覽:476
安卓設置頁面是怎麼 發布:2024-05-21 01:32:51 瀏覽:521
學生成績管理系統資料庫設計 發布:2024-05-21 01:14:41 瀏覽:43
我的世界什麼指令直接出現伺服器 發布:2024-05-21 01:10:00 瀏覽:397
星等演算法 發布:2024-05-21 00:53:06 瀏覽:509
李興華的java視頻 發布:2024-05-21 00:49:55 瀏覽:605
資料庫4種索引類型 發布:2024-05-21 00:47:29 瀏覽:241