2009-08-20 112 views
1

我正在與另一個論壇上的一些開發人員就準確生成MIDI事件(注意消息等)進行辯論。人耳對微小的時序誤差非常敏感,我認爲他們的主要問題來自於他們使用分辨率相對較低的定時器,這些定時器將其事件量化爲15毫秒左右(其大小足以導致可察覺的不準確性)。大約10年前,我寫了一個示例應用程序(Windows 95上的Visual Basic 5),它是一個軟件合成器和MIDI播放器的組合。基本前提是一個跨越緩衝區回放系統,每個緩衝區的持續時間爲十六分音符(例如:每分鐘120個四分音符,每個四分音符爲500毫秒,因此每個十六分音符爲125毫秒,所以每個緩衝區是5513個樣本)。每個緩衝區都通過waveOutWrite方法播放,並使用此方法的回調函數排隊下一個緩衝區併發送MIDI消息。這保持了基於WAV的音頻和MIDI音頻的同步。waveOutWrite API方法的回調的延遲(或延遲)時間是多少?

在我耳邊,這種方法非常奏效 - MIDI音符聽起來甚至略微失調(如果您使用普通定時器精確到15毫秒來播放MIDI音符,它們會聽起來明顯失調)。

理論上,這種方法可以產生精確到樣本的MIDI定時,或0.0227毫秒(因爲每毫秒有44.1個樣本)。我懷疑這是這種方法的真正延遲,因爲大概在緩衝區結束和waveOutWrite回調被通知時間之間有一些小的延遲。有誰知道這個延遲實際上有多大?

+0

來看着你在寫播放同步沒有延遲,延遲在WaveOut中是聲波變化和其實際播放之間的最小延遲。我的經驗是,WaveOut適用於延遲> 64ms(更好的更短的緩衝區最好在我的情況下是8x8ms的緩衝區)。還測試了DirectSound,但它的shit延遲> 400ms(對我的目的不可用),還有bufer查詢回調由於API中的錯誤而無法工作(我有DS最後在XP上測試過,並且沒有使用過)。 – Spektre 2013-09-20 13:53:08

回答

5

默認情況下,Windows調度程序以10ms或16ms的間隔運行,具體取決於處理器。如果你使用timeBeginPeriod()API,你可以改變這個時間間隔(相當大的功耗成本)。

在Windows XP和Windows 7中,wave API的延遲約爲30ms,對於Windows Vista,wave API的延遲約爲50ms。然後您需要添加音頻引擎延遲。

不幸的是,我沒有一個方向上的引擎延遲數字,但我們確實有一些關於引擎延遲的數字 - 我們運行了一個測試,通過USB音頻設備打回了一個音調,並測量了往返延遲(渲染捕獲)。在Vista上,往返延遲約爲80ms,變化約爲10ms。在Win7上,往返延遲約爲40ms,變化約爲5ms。然而,由於音頻硬件引入的延遲量對於每個硬件來說是不同的。

我完全不知道XP音頻引擎或Win9x音頻堆棧的延遲是多少。

+0

這個延遲是否可能是可變的(例如,延遲通常是80ms,但是100次中的1次是150ms或更糟)?如果是這樣,那可能解釋我有一個新問題:http://stackoverflow.com/questions/2303866/how-long-is-the-delay-between-control-invoke-and-the-calling-of-它的代表 – MusiGenesis 2010-02-20 22:16:03

+0

這可能是一個測量小故障 - 如果你在泵通過之間進行測量,你可能會看到高低時間。 – 2010-02-20 23:07:56

1

在最基本的層面上,Windows是一個多線程操作系統。它用100ms的時間片來安排線程。 這意味着,如果沒有CPU爭用,緩衝區結束和waveOutWrite回調之間的延遲可能會很短。或者,如果還有其他忙線程,則必須等待每個線程100毫秒。 然而,在最好的情況下...... CPU的速度現在在GHz。這就使回調在0.000,000,000,1個二級數量級中的調用速度有一個絕對的下限。

除非你能找出你可以在一秒內處理的waveOutWrite回調函數的最大數量,這可能意味着每次調用的延遲,我認爲,實際上,延遲將低於預測的大部分時間那個時候,除非有太多繁忙的線程,否則它會變得非常可怕,可怕的是錯誤的。

1

要添加到上面的很好的答案。

你的問題是關於Windows沒有承諾不會關心的延遲。因此,根據操作系統版本,硬件和其他因素,它可能會有很大的不同。 WaveOut API和DirectSound(不知道WASAPI,但我猜這也適用於這個最新的Vista +音頻API)都設置爲緩衝音頻輸出。只要您正在播放下一個緩衝區時正確播放特定的回調準確性,就不需要了。

當您啓動音頻播放,在播放過程中有幾個假設,如沒有下溢,所有的輸出是連續的,音頻時鐘速度是完全一樣的,你想到的是,如44,100赫茲精確。然後,你可以做簡單的數學計算,以便及時調度波形輸出,將時間轉換爲樣本,然後轉換爲字節。不幸的是,有效的回放速率並不精確,例如,想象一下真實的硬件採樣率可能是44,100 Hz -3%,並且從長遠來看,時間到字節的數學可能讓你失望。一直試圖彌補這種影響,比如使音頻硬件成爲播放時鐘並同步視頻(這就是播放器的工作原理)以及速率匹配技術,以便將輸入數據速率與硬件上的實際播放速率相匹配。這兩者都使得絕對時間測量和延遲成爲相當具有推測性的知識。

更重要的是,API等待時間爲20 ms,30 ms,50 ms等等。很久以前,waveOut API是其他API上的一個層。這意味着某些處理會在數據實際到達硬件之前發生,並且此處理要求您提前將您的手放在排隊的數據上,否則數據將無法到達硬件。比方說,如果您嘗試在播放時間之前將數據排列在10 ms緩衝區中,則API將接受此數據,但它本身會延遲傳遞下游數據,並且揚聲器上會有沉默或舒適噪音。

現在這也與您收到的回調有關。你可以說你不關心緩衝區的延遲,對你來說重要的是精確的回調時間。然而,由於API是分層的,因此你會在內層同步的準確性下收到回調,第二個內層通知空閒緩衝區,第一個內層更新它的記錄並檢查它是否也可以釋放你的緩衝區(嘿,不得不匹配)。這使得回調準確性預期非常薄弱並且不可靠。

只要我還沒有被觸及waveout的API相當長的一段時間內,如果同步精度這樣的問題就來了,我想大概是第一次的兩件事情都想到的:

  • Windows提供訪問音頻硬件時鐘(我知道可通過DirectShow獲得IReferenceClock接口,它可能來自另一個較低級別的東西,也可以訪問),並有可用的,我會盡力與它同步

  • 最新的音頻API來自微軟, WASAPI爲低潛伏期提供特別支持CY音頻與新酷的東西有好等等諸如此類的媒體線程調度,獨佔模式流和< 10毫秒PCM延遲 - 這是更好的同步是在