2013-03-31 84 views
1

我正在爲使用Qt的UI編寫一個模擬器,事件處理等等。顯然,我需要有一個準確的時間參考。現在,我用適當的時間間隔(NTSC爲16.66667ms,PAL爲20ms)使用QTimer,但正如預期的那樣,其準確性是可怕的。有時計時器以50 FPS發射,有時以120 FPS發射。Qt高分辨率定時器

我認識到,大多數操作系統具有一些功能,以提供精確的時間戳下到微(或納米)第二級。 (即在Windows上爲QueryPerformanceCounter)。因爲我已經有了音頻輸出流,所以我不想使用系統時鐘,而是考慮與音頻時鐘同步,但我不認爲Qt提供了這種功能。

什麼是最簡單的(和/或最佳)的方式同步到一些精確的時鐘調用,在正常情況下,在特定的時間間隔的功能,很少有抖動,從C++/Qt的?

回答

3

高分辨率時間戳並不意味着有當高分辨率時間戳的給定值已經達到,這將喚醒一個沉睡的線程內核中的機制。在Qt和Windows上,當你的定時器超時時間足夠短時(< = 10ms IIRC),Qt會強制系統的時間間隔約爲1ms(1000Hz或1024Hz)。

你需要做的是:

  1. 使用QElapsedTimer跟蹤的高分辨率時間(在內部它在Windows上使用性能計數器或任何有給予最高分辨率時)。

  2. 設置基於高分辨率時間從#1的值的計時器期滿。

當然,您需要處理花費時間過長的幀,錯過的定時器等等。但這是讓它正常工作的唯一理智方法。

或者,您可以使用通知時音頻緩衝區已排至一定水平。 Qt 5可能會爲此提供API。

在任何操作系統上生成更好時序的唯一方法是使用除通用計時器滴答以外的專用硬件。這種硬件可能與在環回模式下運行的串行端口一樣簡單。它作爲一個額外的獨立的等待事件源非常有用。音頻緩衝區交換也是定時的好時機。

如果您希望進一步權衡時間精度的功耗,you can dedicate a hyper thread to busy waiting while polling a high resolution time source。這不是一件輕而易舉的事情,但對於某些應用程序來說,對於測試用具來說,這可能是好的。筆記本電腦/筆記本電腦/平板電腦用戶會恨你。

在那裏提出一個解決方案,在沒有真正的(而不是想象的)網卡「定時器」的情況下,不會影響套接字輪詢等待的解決方案。

0

QTimer是一個事件循環計時器。這意味着只有在偶數循環可以處理事件時纔會發送。如果條件「正確」,它也可能跳過。

據我所知,在Qt中沒有可靠的點火計時器。您將不得不使用特定於平臺的呼叫。

一個可能的Qt解決方案可能是與使用msleepusleep進行計數的主GUI線程分開的線程。你可以有一個睡眠一段時間並喚醒的計時器線程,喚醒另一個用信號量做實際工作的線程,然後返回睡眠。工作線程完成一部分工作,然後再次等待信號量。

QThread::sleep不依賴於事件循環,並可能有更好的精度。

+1

此答案符合傳聞。 Qt中的定時器觸發器與底層操作系統提供的定時器一樣好。它沒有更糟。沒有任何神奇的電話會讓事情變得更好。在Windows上,'usleep'和'msleep'具有相同的默認分辨率:15ms。當你用一個短暫的超時時間觸發一個定時器時,Qt會將全局窗口計時器的時鐘週期切換爲1ms,從而消耗功耗以實現定時器精度。沒有「事件」循環這樣的事情。每個線程都有自己的事件循環。沒有人強迫你在GUI事件循環中運行定時器。在單獨的高優先級線程中運行它們。 –