一:背景
在Windows系統下播放多媒體時,需要去精確控制播放過程,如果用Windows產生的WM_TIMER常規定時器來實現,多媒體畫面會出現斷斷續續的現象,原因在於WM_TIMER只能提供大於等於55ms的精確定時。解決辦法就是利用Windows系統本身提供的一個可以精確到1ms的多媒體定時器,它完全可以保證多媒體播放的實時性要求。
在Windows系統下播放多媒體時,需要去精確控制播放過程,如果用Windows產生的WM_TIMER常規定時器來實現,多媒體畫面會出現斷斷續續的現象,原因在於WM_TIMER只能提供大於等於55ms的精確定時。解決辦法就是利用Windows系統本身提供的一個可以精確到1ms的多媒體定時器,它完全可以保證多媒體播放的實時性要求
二:使用函數與變量
1:LARGE_INTEGER
類型是union,用於表示64位有符號整數值.其他定義如下:
typeef union _ LARGE_INTEGER
{
struct
{
DWORD LowPart;
LONG HighPart;
};
LONGLONG QuadPart;
} LARGE_INTEGER;
特 點:如果你有編譯器直接支持64位整數可以直接使用QuadPart(64位),否則分別對LowPart(32位)和HighPart(32位)存取,
HighPart的最高位爲符號位。
表示範圍:--3689348814741910324到+4611686018427387903內存佈局:LARGE_INTEGER的值等4000000000,在內存中的佈局:
00 28 6B EE 00 00 00 00
(低字節 ) (高字節 )
2:BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);
類 型:Win32API
作 用:返回硬件支持的高精度計數器的頻率。
返回值:非零,硬件支持高精度計數器;零,硬件不支持,讀取失敗。
描 述:技術特點供WIN9X使用的高精度定時器,要求計算機從硬件上支持高精度定時器。
2:BOOL QueryPerformanceCounter (LARGE_INTEGER *lpCount);
類 型:Win32API
作 用:返回硬件支持的高精度計數器的頻率技術值。
返回值:非零,硬件支持高精度計數器;零,硬件不支持,讀取失敗。
描 述:
三:實現過程
在定時前應該先調用QueryPerformanceFrequency()函數獲得機器內部計時器的時鐘頻率;
接着在需要嚴格計時的事件發生前和發生之後分別調用QueryPerformanceCounter();
最後利用兩次獲得的計數之差和時鐘頻率,就可以計算出事件經歷的精確時間。
四:示例1 測試函數SLEEP(100)的精確持續時間方法:
LARGE_INTEGER freq; //CUP頻率 LARGE_INTEGER count1; //第一次CPU計數值 LARGE_INTEGER count2; //第二次CPU計數值 double ld_freq = 0.0; double ld_count1 = 0.0; double ld_count2 = 0.0; //獲得時鐘頻率 QueryPerformanceFrequency(&freq); ld_freq=(double)freq.QuadPart; //獲得第一次CPU計數值 QueryPerformanceCounter(&count1); ld_count1=count1.QuadPart; Sleep(100); //獲得第二次CPU計數值 QueryPerformanceCounter(&count2); ld_count2=count2.QuadPart; dfm=(double)(ld_count2-ld_count1); dft=dfm/dff;//獲得對應的時間值
備註:需要注意的是DFT計算的結果單位是秒。
示例2 毫秒級延遲
void Delay_MS(double delay_ms) { LARGE_INTEGER CPU_freq ;//CUP頻率 LARGE_INTEGER CPU_count_base;//開始計數值 LARGE_INTEGER CPU_count_curr;//當前技術值 double passed_time ;//從0開始,過來多長時間 //獲得時鐘頻率 QueryPerformanceFrequency(&CPU_freq); //獲取開始寄存器計數值 QueryPerformanceCounter(&CPU_count_base); //計時等待 do { QueryPerformanceCounter(&CPU_count_curr); passed_time = ((CPU_count_curr.QuadPart - CPU_count_base.QuadPart) * 1000) / CPU_freq.QuadPart; }while (passed_time < delay_ms); }