timeSetEvent设置不同的时间间隔

6742 2017-03-26 10:38:33
做一个播放MID的程序,假设播放的子程序“ sub 播放MID(音符(),时长()) ” 已经做好。

音符()与时长()都是一一对应数组(音量等等其他的就不列出了)。

以下在窗体

Private Sub Form_Load()
lTimeID = timeSetEvent(10, 0, AddressOf TimeProc, 1, 1) '定义用于接收函数返回值的变量
lmmCount = 60
End Sub
Private Sub Form_Unload(Cancel As Integer)
EndCount
End Sub



以下在模块


Option Explicit

Public Declare Function timeSetEvent Lib "winmm.dll" (ByVal uDelay As Long, ByVal _
uResolution As Long, ByVal lpFunction As Long, ByVal dwUser As Long, _
ByVal uFlags As Long) As Long
Public Declare Function timeKillEvent Lib "winmm.dll" (ByVal uID As Long) As Long

Public lmmCount As Single
Public lTimeID As Long '定义用于接收函数返回值的变量

'timeSetEvent的回调函数
Sub TimeProc(ByVal uID As Long, ByVal uMsg As Long, ByVal dwUser As Long, _
ByVal dw1 As Long, ByVal dw2 As Long)

‘ Form1.Text1.Text = Format$(lmmCount, "00.00")
’ lmmCount = lmmCount - 0.01

End Sub

Sub EndCount()
timeKillEvent lTimeID
End Sub


如果想用 timeSetEvent来计时,设定时间间隔,那么上边提到的播放的子程序放在哪里?到网上查找回调函数各参数的含义,也不是很清楚。

再请教各位大师,一般播放工具在处理时的思路是怎么样子的?
...全文
1130 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
6742 2017-06-14
  • 打赏
  • 举报
回复
这个帖子时间有点长了,谢谢 各位老师的参与。结了,谢谢
引用 5 楼 6742 的回复:
假设t表示叠加的时间,if t=1 then Play 音符1 if t=3 then Play 音符2 if t=6 then Play 音符3 ......
就是上边的问题,我新开一个线程,在线程中用循环做,不稳定。 zhao4zhong1老师说“没准得用有限状态自动机的思路”,不理解。
6742 2017-04-01
  • 打赏
  • 举报
回复
#18楼的,还是594.82没有了。是精度问题。#19楼老师的,验证可以,晚上再来学习。 594.85 594.845 594.84 594.835 594.83 594.825 594.81 594.8149 594.80 594.8049 594.79 594.7949 594.78 594.7849
6742 2017-03-31
  • 打赏
  • 举报
回复
用判断来做,也可以的。
Tiger_Zhao 2017-03-31
  • 打赏
  • 举报
回复
A)用 Currency 类型。
B)用 Long 类型,单位是毫秒。
6742 2017-03-31
  • 打赏
  • 举报
回复

Private Sub Command1_Click()
lTimeID = timeSetEvent(10, 0, AddressOf TimeProc, 1, 1)   '定义用于接收函数返回值的变量
lmmCount = 600
End Sub

Private Sub Command2_Click()
EndCount
End Sub

'模块
   Option Explicit
     Public Declare Function timeSetEvent Lib "winmm.dll" (ByVal uDelay As Long, ByVal _
                  uResolution As Long, ByVal lpFunction As Long, ByVal dwUser As Long, _
                  ByVal uFlags As Long) As Long
  Public Declare Function timeKillEvent Lib "winmm.dll" (ByVal uID As Long) As Long
  
   Public lmmCount     As Single
     Public lTimeID     As Long '定义用于接收函数返回值的变量
   
  'timeSetEvent的回调函数
  Sub TimeProc(ByVal uID As Long, ByVal uMsg As Long, ByVal dwUser As Long, _
          ByVal dw1 As Long, ByVal dw2 As Long)
         Form1.Text1.Text = Format$(lmmCount, "00.00")
        lmmCount = lmmCount - 0.01
       
 Debug.Print Format$(lmmCount, "00.00"), lmmCount
 
  End Sub
 
Sub EndCount()
          timeKillEvent lTimeID
 End Sub


下边的数据是“594.82”被略过了,如果播放的时间就是这个,不就少了一个音符?11楼的数据是Single,在回调中DEBUG。PRINT得到的。 594.86 594.855 594.85 594.845 594.84 594.835 594.83 594.825 594.81 594.8149 594.80 594.8049 594.79 594.7949 594.78 594.7849 594.77 594.7749 594.76 594.7649
youyouting 2017-03-31
  • 打赏
  • 举报
回复
我刚才发布了一条人才招聘信息,如果有近期想换工作的,可与我联系。13636381964 上海微晨信息科技有限公司:陈先生
Tiger_Zhao 2017-03-31
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 6742 的回复:]lTimeID = timeSetEvent(100, 1, AddressOf TimeProc, 1, 1)[/Quote]
定时间隔0.1秒,自己累加播放时间的精度也是0.1,哪来的4位小数?
序列中每个音符的开始时间也要取整到精度0.1,怎么可能被略过?

就算不对齐,你不会改为 开始时间<=播放时间 判断啊!
不动脑就别编程序
Tiger_Zhao 2017-03-31
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 Chen8013 的回复:]给你简单的修改一下,你修细看看:这些数据已经不存在“被略过”的问题了。[/Quote]
多此一举,更改数据类型就能解决的
Public lmmCount As Currency
舉杯邀明月 2017-03-31
  • 打赏
  • 举报
回复
引用 15 楼 6742 的回复:
……………… 下边的数据是“594.82”被略过了,如果播放的时间就是这个,不就少了一个音符?11楼的数据是Single,在回调中DEBUG。PRINT得到的。 594.86 594.855 594.85 594.845 594.84 594.835 594.83 594.825 594.81 594.8149 594.80 594.8049 594.79 594.7949 594.78 594.7849 594.77 594.7749 594.76 594.7649
原来你是这样使用的啊。 不过这样并没有什么不对…… 只是你没有正确使用,造成时间精度不够,才引起“问题”。 (你需要有是“10ms”,但实际计时精度为“15ms”,很容易出现“偏差5ms”造成0.01秒的“跳格”) 给你简单的修改一下,你修细看看:这些数据已经不存在“被略过”的问题了。
Option Explicit

Private Declare Function timeBeginPeriod Lib "WinMM" (ByVal uPeriod As Long) As Long
Private Declare Function timeEndPeriod Lib "WinMM" (ByVal uPeriod As Long) As Long

Private Sub Command1_Click()
   Call timeBeginPeriod(10)
   lTimeID = timeSetEvent(10, 0, AddressOf TimeProc, 1, 1)
   lmmCount = 600
End Sub

Private Sub Command2_Click()
   EndCount
   Call timeEndPeriod(10)
End Sub
随意的一次测试结果数据:
599.99         599.99 
599.98         599.98 
599.97         599.97 
599.96         599.96 
599.95         599.95 
599.94         599.9399 
599.93         599.9299 
599.92         599.9199 
599.91         599.9099 
599.90         599.8999 
599.89         599.8899 
599.88         599.8799 
599.87         599.8699 
599.86         599.8599 
599.85         599.8499 
599.84         599.8398 
599.83         599.8298 
599.82         599.8198 
599.81         599.8098 
599.80         599.7998 
599.79         599.7898 
599.78         599.7798 
599.77         599.7698 
599.76         599.7598 
599.75         599.7498 
599.74         599.7397 
599.73         599.7297 
599.72         599.7197 
599.71         599.7097 
599.70         599.6997 
599.69         599.6897 
599.68         599.6797 
599.67         599.6697 
599.66         599.6597 
599.65         599.6497 
599.64         599.6396 
599.63         599.6296 
599.62         599.6196 
599.61         599.6096 
599.60         599.5996 
599.59         599.5896 
599.58         599.5796 
599.57         599.5696 
599.56         599.5596 
599.55         599.5496 
599.54         599.5396 
599.53         599.5295 
599.52         599.5195 
599.51         599.5095 
599.50         599.4995 
599.49         599.4895 
599.48         599.4795 
599.47         599.4695 
599.46         599.4595 
599.45         599.4495 
599.44         599.4395 
599.43         599.4294 
599.42         599.4194 
599.41         599.4094 
599.40         599.3994 
599.39         599.3894 
599.38         599.3794 
599.37         599.3694 
599.36         599.3594 
599.35         599.3494 
599.34         599.3394 
599.33         599.3293 
599.32         599.3193 
599.31         599.3093 
599.30         599.2993 
599.29         599.2893 
599.28         599.2793 
599.27         599.2693 
599.26         599.2593 
599.25         599.2493 
599.24         599.2393 
599.23         599.2292 
599.22         599.2192 
599.21         599.2092 
599.20         599.1992 
599.19         599.1892 
599.18         599.1792 
599.17         599.1692 
599.16         599.1592 
599.15         599.1492 
599.14         599.1392 
599.13         599.1292 
599.12         599.1191 
599.11         599.1091 
599.10         599.0991 
599.09         599.0891 
599.08         599.0791 
599.07         599.0691 
599.06         599.0591 
599.05         599.0491 
599.04         599.0391 
599.03         599.0291 
599.02         599.019 
599.01         599.009 
599.00         598.999 
598.99         598.989 
598.98         598.979 
598.97         598.969 
598.96         598.959 
598.95         598.949 
598.94         598.939 
598.93         598.929 
598.92         598.9189 
598.91         598.9089 
598.90         598.8989 
598.89         598.8889 
598.88         598.8789 
598.87         598.8689 
598.86         598.8589 
598.85         598.8489 
598.84         598.8389 
598.83         598.8289 
598.82         598.8188 
598.81         598.8088 
598.80         598.7988 
598.79         598.7888 
598.78         598.7788 
598.77         598.7688 
598.76         598.7588 
598.75         598.7488 
598.74         598.7388 
598.73         598.7288 
598.72         598.7188 
598.71         598.7087 
598.70         598.6987 
598.69         598.6887 
598.68         598.6787 
598.67         598.6687 
598.66         598.6587 
598.65         598.6487 
598.64         598.6387 
598.63         598.6287 
598.62         598.6187 
598.61         598.6086 
598.60         598.5986 
598.59         598.5886 
598.58         598.5786 
598.57         598.5686 
598.56         598.5586 
598.55         598.5486 
598.54         598.5386 
598.53         598.5286 
598.52         598.5186 
598.51         598.5085 
598.50         598.4985 
598.49         598.4885 
598.48         598.4785 
598.47         598.4685 
598.46         598.4585 
598.45         598.4485 
598.44         598.4385 
598.43         598.4285 
598.42         598.4185 
598.41         598.4084 
598.40         598.3984 
598.39         598.3884 
598.38         598.3784 
598.37         598.3684 
598.36         598.3584 
598.35         598.3484 
598.34         598.3384 
598.33         598.3284 
598.32         598.3184 
598.31         598.3083 
598.30         598.2983 
598.29         598.2883 
598.28         598.2783 
598.27         598.2683 
598.26         598.2583 
598.25         598.2483 
598.24         598.2383 
598.23         598.2283 
598.22         598.2183 
598.21         598.2083 
598.20         598.1982 
598.19         598.1882 
598.18         598.1782 
598.17         598.1682 
598.16         598.1582 
598.15         598.1482 
598.14         598.1382 
598.13         598.1282 
598.12         598.1182 
598.11         598.1082 
598.10         598.0981 
598.09         598.0881 
598.08         598.0781 
598.07         598.0681 
598.06         598.0581 
598.05         598.0481 
598.04         598.0381 
舉杯邀明月 2017-03-30
  • 打赏
  • 举报
回复
你11楼的那些数据结果,是在“回调”中,用单精度变量累加0.01得到的“秒数”吗?
Tiger_Zhao 2017-03-30
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 6742的回复:]由于精度问题,有时并不一定能找到t,应该播放的那个音符就会被略过 [/Quote]

播放时间进行累加,只可能是 00:01、00:02、00:03,怎么可能略过???
6742 2017-03-30
  • 打赏
  • 举报
回复


前边的 lmmCount改一下,就会有上边的图片。 Debug.Print lmmCount放在回调函数中。

lmmCount = 600
lTimeID = timeSetEvent(100, 1, AddressOf TimeProc, 1, 1)

如果精度高(timeSetEvent,第二个参数设置为0),出现的“略过”时间会长一些。
笨狗先飞 2017-03-29
  • 打赏
  • 举报
回复
计时精度如果是秒级的,用timer控件interval设置在100,然后监控second(now)的变化就可以了, 如果是毫秒级恐怕达不到了
6742 2017-03-29
  • 打赏
  • 举报
回复
引用 6 楼 Tiger_Zhao的回复:
在序列里找匹配的t啊。
都不用“找”,有序的序列,只要判断下一个未播放的是否匹配t。
由于精度问题,有时并不一定能找到t,应该播放的那个音符就会被略过
6742 2017-03-28
  • 打赏
  • 举报
回复
播放序列表示为 {{00:00,音符1,1秒},{00:01,音符2,3秒},{00:04,音符3,6秒},{00:10,END}} 假设t表示叠加的时间,if t=1 then Play 音符1 if t=3 then Play 音符2 if t=6 then Play 音符3 ...... 这些如何写,放在回调函数里边,还是外边?
Tiger_Zhao 2017-03-28
  • 打赏
  • 举报
回复
计算出开始时间,播放序列表示为 {{00:00,音符1,1秒},{00:01,音符2,3秒},{00:04,音符3,6秒},{00:10,END}};
初始化播放时间为 00:00,播放音符1;
timeSetEvent 定时1秒;
TimeProc 对播放时间进行累加(每次1秒),根据播放序列,分别在 00:01/00:04 的时候播放 音符2/音符3,在 00:10 时结束定时。
赵4老师 2017-03-28
  • 打赏
  • 举报
回复
没准得用有限状态自动机的思路。
Tiger_Zhao 2017-03-28
  • 打赏
  • 举报
回复
在序列里找匹配的t啊。
都不用“找”,有序的序列,只要判断下一个未播放的是否匹配t。
Tiger_Zhao 2017-03-27
  • 打赏
  • 举报
回复
看错了,你已经有调用了,请忽略#1。

假定你把 {音符,时长} 保持在数组中,那么时长逐个累加,可以计算出每个音符的开始时间。
TimeProc 回调一次就是累加一次播放时长;
下个音符的开始时间到了,就播放;
否则继续等。
Tiger_Zhao 2017-03-27
  • 打赏
  • 举报
回复
lTimeID = timeSetEvent(0, 0, AddressOf TimeProc, 0, 0)

关键就是 AddressOf 的用法,其它几个参数我随便写的,你自己改正确。
加载更多回复(1)

1,486

社区成员

发帖
与我相关
我的任务
社区描述
VB API
社区管理员
  • API
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧