audio unity 加速_淺談Unity中Android、iOS音頻延遲

在Unity上面做音游,當在移動端實機運行起來,會發現,音頻的發出會有一定的延遲,無論是長音效還是短音效,Unity內置的Audio內部使用的是FMOD,有以下手段改善

通過設置稍微改善其延遲的問題

Edit → Project Settings → Audio → 設置DSP Buffer size為Best latency(設置 dsp 緩沖區大小以優化延遲或性能,設置一個不合適的值會導致安卓設備的電流音)

音頻文件的Load Type為Decompress On Load(讓音頻提前讀取到緩存中)

讓音頻文件越小越好

代碼來獲取準確的音軌采樣時間

糟糕的方式

AudioSource audioSource;

//100ms延遲

float GetTrackTime()

{

return audioSource.time;

}

好的方式

//20ms延遲

float GetTrackTime()

{

return 1f * audioSource.timeSamples / audioSource.clip.frequency;

}

更好的方式

double trackStartTime;

void StartMusic()

{

trackStartTime = AudioSettings.dspTime + 1;

audioSource.PlayScheduled(trackStartTime);

}

double GetTrackTime()

{

return AudioSettings.dspTime - trackStartTime;

}

最好的方式

Stopwatch stopwatch = new Stopwatch();

void StartMusic()

{

audioSource.Play();

stopwatch.Start();

}

double GetTrackTime()

{

return stopwatch.ElapsedMilliseconds/1000f;

}

//timeSample的Get方法受限與音頻異步的問題是有20ms的延遲的,但是Set方法幾乎沒有延遲

void SetTrackTime(float time)

{

audioSource.timeSample = (int)(time * audioSource.clip.frequency);

}

但是結果往往還是無法讓人滿意,經過測試,iOS大多數設備的延遲降到10ms以內,誤差范圍外,相當于沒有了,但是安卓設備的延遲根據機型的不同有不同的延遲,大約在100ms~500ms:

image.png

硬件和軟件的原因造成了Android設備的延遲偏高以及不統一

音頻播放的不同階段

模擬音頻輸入

可能有幾種不同的模擬組件,例如內置麥克風的前置放大器。在這種情況下,這些模擬組件可被視為“零延遲”,因為它們的真實延遲通常低于1 ms。

延遲:0

模數轉換(ADC)

音頻芯片以預定義的間隔測量輸入的音頻流,并將每個測量值轉換為數字。此預定義間隔稱為采樣率,以Hz為單位。我們的移動音頻普查和延遲測試應用程序顯示,48000 Hz是Android和iOS設備上大多數音頻芯片的原生采樣率,這意味著音頻流每秒采樣48000次。

由于ADC實現通常在內部包含過采樣濾波器,因此經驗法則是將ADC步長歸因于1 ms延遲。

現在音頻流已經數字化,從這一點開始,音頻流現在是數字音頻。數字音頻幾乎不會一個接一個地傳播,而是以塊狀稱,稱為“緩沖區”或“周期”。

延遲:1毫秒

總線從音頻芯片傳輸到音頻驅動器

音頻芯片有幾個任務。它處理ADC和DAC,在多個輸入和輸出之間切換或混合,應用音量等。它還將離散數字音頻樣本“分組”到緩沖區中,并處理這些緩沖區到操作系統的傳輸。

音頻芯片通過總線連接到CPU,例如USB,PCI,Firewire等。每個總線都有自己的傳輸延遲,具體取決于其內部緩沖區大小和緩沖區計數。此處的延遲通常為1 ms(內部系統總線上的音頻芯片)至6 ms(具有保守USB總線設置的USB聲卡)。

延遲:1-6毫秒

音頻驅動程序(ALSA,OSS等)

音頻驅動器使用音頻芯片的本機采樣率(大多數情況下為48000 Hz)以“總線緩沖區大小”步驟將輸入音頻接收到環形緩沖器中。

此環形緩沖區在平滑總線傳輸抖動(“粗糙度”)中起著重要作用,并將總線傳輸緩沖區大小“連接”到操作系統音頻堆棧的緩沖區大小。從環形緩沖區消耗數據發生在操作系統音頻堆棧的緩沖區大小中,因此它自然會增加一些延遲。

Android運行在Linux的“頂部”,大多數Android設備使用最流行的Linux音頻驅動程序系統ALSA(高級Linux聲音架構)。ALSA像這樣處理環形緩沖區:

音頻以“周期大小”步驟從環形緩沖器中消耗。

環形緩沖區的大小是“周期大小”的倍數。

例如:

周期大小= 480個樣本。

期間數= 2。

環形緩沖區的大小為480x2 = 960個樣本。

音頻輸入接收到一個周期(480個樣本),而音頻堆棧讀取/處理另一個周期(480個樣本)。

延遲= 1個周期,480個樣本。它等于48000 Hz時的10 ms。

環形緩沖液(960個樣品)

期間(480個樣本) 期間(480個樣本)

常見的周期數為2,但有些系統可能會更高。

延遲:一個或多個時期

Android音頻硬件抽象層(HAL)

HAL充當Android媒體服務器和Linux音頻驅動程序之間的中間人。在將Android“移植”到設備上時,移動設備的制造商提供HAL實現。

實現是開放的,供應商可以自由創建任何類型的HAL代碼。使用預定義的結構進行與媒體服務器的通信。媒體服務器加載HAL并要求創建具有可選首選參數的輸入或輸出流,例如采樣率,緩沖區大小或音頻效果。

注意:HAL可能會也可能不會根據參數執行,并且媒體服務器必須“適應”HAL。

典型的HAL實現是tinyALSA,用于與ALSA音頻驅動程序通信。一些供應商在這里提供了封閉的源代碼來實現他們認為重要的音頻功

在分析Android源存儲庫中的許多開源HAL實現的代碼之后,我們發現了一些怪癖,由于奇怪的配置和糟糕的編碼而不必要地增加了音頻路徑的大量延遲和CPU負載。

一個好的HAL實現不應該添加任何延遲。

延遲:0個或更多樣本

Audio Flinger

Android媒體服務器包含兩項服務:

AudioPolicy服務處理音頻會話和權限處理,例如啟用麥克風訪問或呼叫中斷。它與iOS的音頻會話處理非常相似。

Audio Flinger服務處理數字音頻流。

Audio Flinger創建了一個RecordThread,它充當應用程序和音頻驅動程序之間的中間人。它的基本工作是:

使用Android HAL從驅動程序的環形緩沖區中獲取下一個輸入音頻緩沖區。

如果應用程序請求的采樣率與本機采樣率不同,則重新采樣緩沖區。

如果應用程序請求的緩沖區大小不同于本機周期大小,則執行其他緩沖。

如果按照這種方式配置Android,音頻Flinger有一個“快速混音器”路徑。如果用戶應用程序使用本機(Android NDK)代碼并設置具有本機硬件采樣率和周期大小的音頻緩沖區隊列,則不會在此步驟中進行重新采樣,額外緩沖或混合(“MixerThread”)。

RecordThread使用“推”方法,沒有與音頻驅動程序的任何嚴格同步。它試圖在醒來和跑步時進行“有根據的猜測”,但“推”方法對輟學者更敏感。低延遲系統始終使用“拉”方法,其中音頻驅動程序通過整個音頻鏈“指示”音頻i / o。很明顯,當最初構思,設計和開發Android OS時,低延遲音頻不是優先考慮的事情。

延遲:1個周期(最佳情況)

Binder

Android主進程間通信系統中的共享內存用于在Audio Flinger和用戶應用程序之間傳輸音頻緩沖區。它是Android的核心,在Android內部隨處使用。

延遲:0

AudioRecord

我們現在處于用戶應用程序的過程中。AudioRecord實現音頻輸入的應用程序端。這是一個可通過OpenSL ES訪問的客戶端庫功能。

AudioRecord運行一個線程,定期從Audio Flinger獲取一個新緩沖區,其音頻Flinger描述了“推送”理念。如果開發人員將其設置為僅使用一個緩沖區,則不會為音頻路徑添加延遲。

延遲:0+樣本

用戶應用程序

最后,音頻輸入到達其目的地,即用戶應用程序。

由于輸入和輸出線程不相同,因此用戶應用程序必須在線程之間實現環形緩沖區。它的大小最小為2個周期(1個用于音頻輸入,1個用于音頻輸出),但寫得不好的應用程序通常使用暴力并使用更多周期來解決CPU瓶頸。

從這一點開始,我們開始帶著一些音頻輸出返回。

延遲:超過1個周期,通常接近2個(最佳情況)

AudioTrack

AudioTrack實現音頻輸出的用戶應用程序。這是一個可通過OpenSL ES訪問的客戶端庫功能。它運行一個線程,定期將下一個音頻緩沖區發送到Audio Flinger。在Android 4.4.4之后,AudioTrack不會為音頻路徑添加延遲,因為它可以設置為僅使用一個緩沖區。

延遲:0+樣本

Audio Flinger

創建一個PlaybackThread,它作為音頻輸入中描述的RecordThread的反轉。

延遲:1期(最佳情況)

Android音頻HAL

與音頻輸入相同。

延遲:0個或更多樣本

音頻驅動程序(ALSA,OSS等)

音頻驅動器中的音頻輸出與音頻輸入的工作方式相同,也使用環形緩沖器。

延遲:一個或多個時期

總線從音頻驅動器傳輸到音頻芯片

與音頻輸入的總線傳輸類似,此處的延遲通常為1 ms至6 ms。

延遲:1-6毫秒

數模轉換(DAC)

在這一點上,ADC的反轉,數字音頻被“轉換”回模擬。出于與ADC相同的原因,經驗法則是假設DAC有1 ms的延遲。

延遲:1毫秒

模擬音頻輸出

DAC的輸出信號是模擬音頻,但它需要額外的組件來驅動連接的設備,如耳機。與模擬音頻輸入類似,模擬組件可被視為“零延遲”。

延遲:0

解決方案

在所有階段中,除非重寫安卓底層音頻系統,否則我們開發者能夠操作的部分只有音頻的播放方式,目前安卓原生的播放方式有三種:

MediaPlayer

SoundPool

AudioTrack(OpenSL)

AAudio

第一種用于長音頻播放,實際測試結果為音頻延遲依然十分大100ms~500ms之間

第二種和第三種用于短音頻播放,短音頻的播放延遲得到了很大的改善,基本徘徊在50ms之間

但是由于無法應用于長音頻的播放,問題依舊還是沒得到解決

image.png

現有的解決方案推薦

superpowered

致力于安卓低延遲做底層開發的C++ API

NativeAudio

Unity插件,泰國音頻大佬

Unity2019

聽說2019優化了底層音頻的播放機制

關于長音頻的延遲在各個機型上的不同而無法自動修正的解決方案

收集各種機型預設一個延遲的值

設計一個體驗良好的界面可以幫助用戶設置這個延遲的值

Unity2017默認音頻、NativeAudio(OpenSL)、Criware(OpenSL)、Unity2019(OpenSL)默認音頻延遲比較

短音效

單位是10ms

短音效延遲上NativeAudio和Criware是最低的,也是差不多的。

長音效

誤差范圍內的差距

效率待實驗。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/453773.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/453773.shtml
英文地址,請注明出處:http://en.pswp.cn/news/453773.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

深度學習之 hard negative mining (難例挖掘)

Hard Negative Mining Method 思想 hard是困難樣本,negative是負樣本,hard negative就是說在對負樣本分類時候,loss比較大(label與prediction相差較大)的那些樣本,也可以說是容易將負樣本看成正樣本的那些…

單列表_使用Excel中的quot;記錄單quot;功能快速錄入數據

在Excel中進行數據錄入的時候,平常都是一行一行地錄入數據,但是有時候在單元格之間,行與行,列與列之間頻繁地切換去錄入數據,費事費力還容易出錯。今天給你推薦一個既好用又有效率的Excel中的隱藏功能——“記錄單”。…

CentOS 6.9下的Setup工具(用于管理服務/防火墻/網絡配置/驗證服務)

說明:Setup工具套件好像是CentOS下特有的用于管理服務/防火墻/網絡配置等,其實就是基于命令行模式界面的GUI工具。唯一特點就是方便。 安裝: #安裝Setup命令工具 yum -y install setuptool #安裝Setup工具配套的系統服務組件 yum -y insta…

wireshark解析rtp協議,流媒體中的AMR/H263/H264包的方法

原文教程:http://hi.baidu.com/zjxiaoyu3/blog/item/22f9f18f32b45de5f11f3670.html 抓到完整的流媒體包之后,用wireshark打開,其中的包可能不會自動映射成RTP+AMR/H263/H264的包,做如下修改操作…

深度學習之非極大值抑制(Non-maximum suppression,NMS)

非極大值抑制(Non-maximum suppression,NMS)是一種去除非極大值的算法,常用于計算機視覺中的邊緣檢測、物體識別等。 算法流程 給出一張圖片和上面許多物體檢測的候選框(即每個框可能都代表某種物體)&…

148. 顏色分類

給定一個包含紅,白,藍且長度為 n 的數組,將數組元素進行分類使相同顏色的元素相鄰,并按照紅、白、藍的順序進行排序。 我們可以使用整數 0,1 和 2 分別代表紅,白,藍。 注意事項 不能使用代碼庫中…

vue項目token放在哪里_關于vue動態菜單的那點事

vue-element-admin4.0國內節點訪問地址:https://panjiachen.gitee.io/vue-element-admin-site/zh/本此使用的是https://github.com/PanJiaChen/vue-element-admin/tree/i18n 國際化分支的版本。說是除了國際化其他都一樣。本文主要介紹前臺動態的使用資源權限。后臺…

H264學習方法歷程資料

我的H.264學習歷程 半年前,我知道了H.264這個名詞。那個時候決定學習H.264,可是我連資料都不知道如何收集。而且整個學校就只有我一個人在學習H.264, 找不到人交流,所以那個時候學得真的是舉步維艱,很痛苦&#xff0c…

深度學習之 ROI Pooling

什么是ROI? ROI是 Region of interest 的簡寫,指的是 Faster R-CNN 結構中,經過 RPN 層后,產生的 proposal 對應的 box 框。 ROI Pooling 顧名思義,是 pooling 層的一種,而且是針對 ROIs 的 pooling。整個…

KD樹小結

很久之前我就想過怎么快速在二維平面上查找一個區域的信息,思考許久無果,只能想到幾種優秀一點的暴力。 KD樹就是干上面那件事的。 別的不多說,趕緊把自己的理解寫下來,免得涼了。 KD樹的組成 以維護k維空間(x,y,……)內的KD樹為例…

多元函數求極值中的a_多元函數的條件極值和拉格朗日乘數法

、條件極值、拉格朗日乘數法1. 轉化為無條件極值在討論多元函數極值問題時,如果遇到除了在定義域中尋求駐點(可能的極值點)外,對自變量再無別的限制條件,我們稱這類問題為函數的無條件極值。如求的極值,就是無條件極值問題。然而在…

深度學習之 RPN(RegionProposal Network)- 區域候選網絡

anchor boxes基本概念與作用: feature map 上的一個點可以映射回輸入圖片上的一個點,以特征圖上這個點為中心,預先人為設定 k 個 boxes,這些 boxes 就稱為在這個點上生成的 k 個 anchor boxes(所有anchor boxes的中心點坐標是一樣…

h264的碼率控制 JVT-G012

開始看h264的碼率控制,很多地方都提到 G012,拿來做為參考比較,看來很有必要研究清楚。 偶這人,E文文檔不翻譯的話,看過就忘了,于是草草翻譯了下,因為不打算做B幀,也不準備在同一幀中…

Android RecyclerView嵌套EditView實時更新Item數據

一、場景(例如:購物車) 1、當我們需要以列表樣式管理某些數據時,可能需要列表項的某個字段可編輯 2、編輯Item上的某個字段后可能還要更新相關字段的值 二、可能遇到的問題 1、列表滑動導致輸入框中的數據錯位(或者焦點…

workbench拓撲優化教程_優化技術在水泵水力設計的應用(上篇)

文章來源:安世亞太官方訂閱號(搜索:Peraglobal)CFD技術在泵的內流數值模擬、研究泵內部流動規律和結構方面已廣泛應用,取得了很多成果。但是初步設計的產品如果通過CFD仿真得到的性能曲線不能滿足使用要求,…

深度學習之 TensorRT

1 簡介 TensorRT是一個高性能的深度學習推理(Inference)優化器,可以為深度學習應用提供低延遲、高吞吐率的部署推理。TensorRT可用于對超大規模數據中心、嵌入式平臺或自動駕駛平臺進行推理加速。TensorRT現已能支持TensorFlow、Caffe、Mxne…

H.264筆記

H.264標準寫得比較繁復,所以考慮在瀏覽完Whitepaper之后就開始研讀X264代碼。X264代碼風格還是比較清晰簡潔的。根據對標準得理解,Picture Order Count在Slice解碼的一開始就被提及:I0 B1 B2 P3 B4 B5 P6I0 P3 B1 B2 P6 B4 B5于是I0的POC是0&…

進制轉換中dbho是什么意思_什么是網段?二進制十進制如何互相轉換?看完這篇,你就全明白了...

之前的文章講了ip,子網掩碼,網關的關系,今天著重講一下網段。我們用傻瓜交換機通訊時,一個網段的設備才能互相通訊,怎么能判斷兩個ip是同一個網段呢?今天就簡單的說一下。(這篇文章用語音聽可以起到催眠作用…

【網絡流24題】星際轉移問題(最大流)

【網絡流24題】星際轉移問題(最大流) 題面 Cogs 題解 因為天數是未知的,所以我們要想辦法處理天數 可以選擇二分或者依次累加天數 因為數據范圍較小,使用二分可能反而復雜度會增高 所以使用不斷累加天數 那么,把所有的…

使用 gunicorn 部署flask項目

1、WSGI協議 Web框架致力于如何生成HTML代碼,而Web服務器用于處理和響應HTTP請求。Web框架和Web服務器之間的通信,需要一套雙方都遵守的接口協議。WSGI協議就是用來統一這兩者的接口的。 2、WSGI容器 常用的WSGI容器有Gunicorn和uWSGI,但G…