一:背景
在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); }