日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

audio unity 加速_浅谈Unity中Android、iOS音频延迟

發(fā)布時間:2023/12/20 Android 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 audio unity 加速_浅谈Unity中Android、iOS音频延迟 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

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

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

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

音頻文件的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);

}

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

image.png

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

音頻播放的不同階段

模擬音頻輸入

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

延遲:0

模數(shù)轉換(ADC)

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

由于ADC實現(xiàn)通常在內(nèi)部包含過采樣濾波器,因此經(jīng)驗法則是將ADC步長歸因于1 ms延遲。

現(xiàn)在音頻流已經(jīng)數(shù)字化,從這一點開始,音頻流現(xiàn)在是數(shù)字音頻。數(shù)字音頻幾乎不會一個接一個地傳播,而是以塊狀稱,稱為“緩沖區(qū)”或“周期”。

延遲:1毫秒

總線從音頻芯片傳輸?shù)揭纛l驅動器

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

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

延遲:1-6毫秒

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

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

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

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

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

環(huán)形緩沖區(qū)的大小是“周期大小”的倍數(shù)。

例如:

周期大小= 480個樣本。

期間數(shù)= 2。

環(huán)形緩沖區(qū)的大小為480x2 = 960個樣本。

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

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

環(huán)形緩沖液(960個樣品)

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

常見的周期數(shù)為2,但有些系統(tǒng)可能會更高。

延遲:一個或多個時期

Android音頻硬件抽象層(HAL)

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

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

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

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

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

一個好的HAL實現(xiàn)不應該添加任何延遲。

延遲:0個或更多樣本

Audio Flinger

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

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

Audio Flinger服務處理數(shù)字音頻流。

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

使用Android HAL從驅動程序的環(huán)形緩沖區(qū)中獲取下一個輸入音頻緩沖區(qū)。

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

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

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

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

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

Binder

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

延遲:0

AudioRecord

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

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

延遲:0+樣本

用戶應用程序

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

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

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

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

AudioTrack

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

延遲:0+樣本

Audio Flinger

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

延遲:1期(最佳情況)

Android音頻HAL

與音頻輸入相同。

延遲:0個或更多樣本

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

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

延遲:一個或多個時期

總線從音頻驅動器傳輸?shù)揭纛l芯片

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

延遲:1-6毫秒

數(shù)模轉換(DAC)

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

延遲:1毫秒

模擬音頻輸出

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

延遲:0

解決方案

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

MediaPlayer

SoundPool

AudioTrack(OpenSL)

AAudio

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

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

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

image.png

現(xiàn)有的解決方案推薦

superpowered

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

NativeAudio

Unity插件,泰國音頻大佬

Unity2019

聽說2019優(yōu)化了底層音頻的播放機制

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

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

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

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

短音效

單位是10ms

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

長音效

誤差范圍內(nèi)的差距

效率待實驗。

總結

以上是生活随笔為你收集整理的audio unity 加速_浅谈Unity中Android、iOS音频延迟的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。