试一试这个,你的代码有误,我修改如下:Option ExplicitPrivate Declare Function midiOutClose Lib "winmm.dll" (ByVal hMidiOut As Long) As Long Private Declare Function midiOutOpen Lib "winmm.dll" (lphMidiOut As Long, ByVal uDeviceID As Long, ByVal dwCallback As Long, ByVal dwInstance As Long, ByVal dwFlags As Long) As Long Private Declare Function midiOutShortMsg Lib "winmm.dll" (ByVal hMidiOut As Long, ByVal dwMsg As Long) As Long Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)Private Sub Command1_Click() Dim lMidiAPIReturn As Long Dim tone As Integer Dim mlmidiouthandle As Long Dim volume As Long Dim channel As Long
lMidiAPIReturn = midiOutShortMsg(mlmidiouthandle, &H90 + ((tone) * &H100) + (volume * &H10000) + channel) Sleep 1000 midiOutClose mlmidiouthandle End Sub
本帖最后由 bcrun 于 2011-05-27 08:56:03 编辑
为方便阅读,我重发如下: Option Explicit Private Declare Function midiOutClose Lib "winmm.dll" (ByVal hMidiOut As Long) As Long Private Declare Function midiOutOpen Lib "winmm.dll" (lphMidiOut As Long, ByVal uDeviceID As Long, ByVal dwCallback As Long, ByVal dwInstance As Long, ByVal dwFlags As Long) As Long Private Declare Function midiOutShortMsg Lib "winmm.dll" (ByVal hMidiOut As Long, ByVal dwMsg As Long) As Long Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) Dim notes(1 To 8, 1 To 2) As Variant Dim i, j, k, s(8) As Integer Dim cf As Boolean Private Sub Form_Load() notes(1, 1) = "C4": notes(1, 2) = 60 notes(2, 1) = "D4": notes(2, 2) = 62 notes(3, 1) = "E4": notes(3, 2) = 64 notes(4, 1) = "F4": notes(4, 2) = 65 notes(5, 1) = "G4": notes(5, 2) = 67 notes(6, 1) = "A5": notes(6, 2) = 69 notes(7, 1) = "B5": notes(7, 2) = 71 notes(8, 1) = "C5": notes(8, 2) = 72 End Sub Private Sub Command2_Click() Dim lMidiAPIReturn As Long Dim tone As Integer Dim mlmidiouthandle As Long Dim volume As Long Dim channel As Long Dim i As Integer mlmidiouthandle = 0 lMidiAPIReturn = midiOutOpen(mlmidiouthandle, -1, 0, 0, 0) volume = 90 channel = 0 i = 1 Text1.Text = "" Do While i <= 8 '第一层循环,用于取8个数 cf = False '是否取到了重复的数 Randomize k = Int(Rnd() * 8) + 1 '获取随机数 For j = 1 To i '第二层循环,判断是否取到的数字发生了重复 If k = s(j) Then '当发生重复的时候标记cf变量 cf = True Exit For End If Next If cf = False Then '如果取得数字没有重复,进行赋值,并显示在text1文本框 'Text1.Text = Text1.Text & k & Chr(13) & Chr(10) s(i) = k tone = notes(k, 2) 'MsgBox tone lMidiAPIReturn = midiOutShortMsg(mlmidiouthandle, &H90 + ((tone) * &H100) + (volume * &H10000) + channel) Sleep 100 'MsgBox (s(i)) Text1.Text = Text1.Text + Str(s(i)) i = i + 1 '继续取下一个数字,直到i=8 End If Loop End Sub
谢几位的补充,我加上了,如下行红色,好使,但是: 当我按Command2达到十多次时(比如11次或16次不等),就不出声了,最后一次出声时还会拖长声音,我每次都是等最后的声响完才又按的,是不是还得加什么语句? 请大师们斧正!Option Explicit Private Declare Function midiOutClose Lib "winmm.dll" (ByVal hMidiOut As Long) As Long Private Declare Function midiOutOpen Lib "winmm.dll" (lphMidiOut As Long, ByVal uDeviceID As Long, ByVal dwCallback As Long, ByVal dwInstance As Long, ByVal dwFlags As Long) As Long Private Declare Function midiOutShortMsg Lib "winmm.dll" (ByVal hMidiOut As Long, ByVal dwMsg As Long) As Long Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) Dim notes(1 To 8, 1 To 2) As Variant Dim i, j, k, s(8) As Integer Dim cf As Boolean Private Sub Form_Load() notes(1, 1) = "C4": notes(1, 2) = 60 notes(2, 1) = "D4": notes(2, 2) = 62 notes(3, 1) = "E4": notes(3, 2) = 64 notes(4, 1) = "F4": notes(4, 2) = 65 notes(5, 1) = "G4": notes(5, 2) = 67 notes(6, 1) = "A5": notes(6, 2) = 69 notes(7, 1) = "B5": notes(7, 2) = 71 notes(8, 1) = "C5": notes(8, 2) = 72 End Sub Private Sub Command2_Click() Dim lMidiAPIReturn As Long Dim tone As Integer Dim mlmidiouthandle As Long Dim volume As Long Dim channel As Long Dim i As Integer mlmidiouthandle = 0 lMidiAPIReturn = midiOutOpen(mlmidiouthandle, -1, 0, 0, 0) volume = 90 channel = 0 i = 1 Text1.Text = "" Do While i <= 8 '第一层循环,用于取8个数 cf = False '是否取到了重复的数 Randomize k = Int(Rnd() * 8) + 1 '获取随机数 For j = 1 To i '第二层循环,判断是否取到的数字发生了重复 If k = s(j) Then '当发生重复的时候标记cf变量 cf = True Exit For End If Next If cf = False Then '如果取得数字没有重复,进行赋值,并显示在text1文本框 'Text1.Text = Text1.Text & k & Chr(13) & Chr(10) s(i) = k tone = notes(k, 2) 'MsgBox tone lMidiAPIReturn = midiOutShortMsg(mlmidiouthandle, &H90 + ((tone) * &H100) + (volume * &H10000) + channel) Sleep 100 'MsgBox (s(i)) Text1.Text = Text1.Text + Str(s(i)) i = i + 1 '继续取下一个数字,直到i=8 End If DoEvents Loop lMidiAPIReturn = midiOutClose(mlmidiouthandle) End Sub
上面倒数第二行有问题,重发如下: Option Explicit Private Declare Function midiOutClose Lib "winmm.dll" (ByVal hMidiOut As Long) As Long Private Declare Function midiOutOpen Lib "winmm.dll" (lphMidiOut As Long, ByVal uDeviceID As Long, ByVal dwCallback As Long, ByVal dwInstance As Long, ByVal dwFlags As Long) As Long Private Declare Function midiOutShortMsg Lib "winmm.dll" (ByVal hMidiOut As Long, ByVal dwMsg As Long) As Long Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) Dim notes(1 To 8, 1 To 2) As Variant Dim i, j, k, s(8) As Integer Dim cf As Boolean Private Sub Form_Load() notes(1, 1) = "C4": notes(1, 2) = 60 notes(2, 1) = "D4": notes(2, 2) = 62 notes(3, 1) = "E4": notes(3, 2) = 64 notes(4, 1) = "F4": notes(4, 2) = 65 notes(5, 1) = "G4": notes(5, 2) = 67 notes(6, 1) = "A5": notes(6, 2) = 69 notes(7, 1) = "B5": notes(7, 2) = 71 notes(8, 1) = "C5": notes(8, 2) = 72 End Sub Private Sub Command2_Click() Dim lMidiAPIReturn As Long Dim tone As Integer Dim mlmidiouthandle As Long Dim volume As Long Dim channel As Long Dim i As Integer mlmidiouthandle = 0 lMidiAPIReturn = midiOutOpen(mlmidiouthandle, -1, 0, 0, 0) volume = 90 channel = 0 i = 1 Text1.Text = "" Do While i <= 8 '第一层循环,用于取8个数 cf = False '是否取到了重复的数 Randomize k = Int(Rnd() * 8) + 1 '获取随机数 For j = 1 To i '第二层循环,判断是否取到的数字发生了重复 If k = s(j) Then '当发生重复的时候标记cf变量 cf = True Exit For End If Next If cf = False Then '如果取得数字没有重复,进行赋值,并显示在text1文本框 'Text1.Text = Text1.Text & k & Chr(13) & Chr(10) s(i) = k tone = notes(k, 2) 'MsgBox tone lMidiAPIReturn = midiOutShortMsg(mlmidiouthandle, &H90 + ((tone) * &H100) + (volume * &H10000) + channel) Sleep 100 'MsgBox (s(i)) Text1.Text = Text1.Text + Str(s(i)) i = i + 1 '继续取下一个数字,直到i=8 End If DoEvents Loop lMidiAPIReturn = midiOutClose(mlmidiouthandle) End Sub
楼主精神可嘉!Option Explicit Private Declare Function midiOutClose Lib "winmm.dll" (ByVal hMidiOut As Long) As Long Private Declare Function midiOutOpen Lib "winmm.dll" (lphMidiOut As Long, ByVal uDeviceID As Long, ByVal dwCallback As Long, ByVal dwInstance As Long, ByVal dwFlags As Long) As Long Private Declare Function midiOutShortMsg Lib "winmm.dll" (ByVal hMidiOut As Long, ByVal dwMsg As Long) As Long Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) '-------------------------------------------------------- Dim notes(1 To 8, 1 To 2) As Variant '-------------------------------------------------------- Private Sub Form_Load() Randomize '此语句应在初始化时调用一次即可 notes(1, 1) = "C4": notes(1, 2) = 60 notes(2, 1) = "D4": notes(2, 2) = 62 notes(3, 1) = "E4": notes(3, 2) = 64 notes(4, 1) = "F4": notes(4, 2) = 65 notes(5, 1) = "G4": notes(5, 2) = 67 notes(6, 1) = "A5": notes(6, 2) = 69 notes(7, 1) = "B5": notes(7, 2) = 71 notes(8, 1) = "C5": notes(8, 2) = 72 End Sub '-------------------------------------------------------- Private Sub Command2_Click() Dim lMidiAPIReturn As Long Dim tone As Integer Dim mlmidiouthandle As Long Dim volume As Long Dim channel As Long Dim i As Integer Dim a As Integer Dim b As Integer Dim t As Integer Dim s(8) As Integer For i = 1 To 8 s(i) = i Next '随机打乱s(i)的顺序 即洗牌 For i = 8 To 2 Step -1 a = i: b = Int(Rnd() * i) + 1 If a <> b Then t = s(a): s(a) = s(b): s(b) = t End If Next mlmidiouthandle = 0 lMidiAPIReturn = midiOutOpen(mlmidiouthandle, -1, 0, 0, 0) volume = 90 channel = 0 Text1.Text = "" For i = 1 To 8 Text1.Text = Text1.Text + CStr(s(i)) + " " + notes(s(i), 1) + ", " Text1.Refresh tone = notes(s(i), 2) lMidiAPIReturn = midiOutShortMsg(mlmidiouthandle, &H90 + ((tone) * &H100) + (volume * &H10000) + channel) Sleep 100 Next lMidiAPIReturn = midiOutClose(mlmidiouthandle) End Sub
返回值为4,也就是说并没有打开MIDI设备
Private Declare Function midiOutOpen Lib "winmm.dll" (lphMidiOut As Long, ByVal uDeviceID As Long, ByVal dwCallback As Long, ByVal dwInstance As Long, ByVal dwFlags As Long) As Long
Private Declare Function midiOutShortMsg Lib "winmm.dll" (ByVal hMidiOut As Long, ByVal dwMsg As Long) As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)Private Sub Command1_Click()
Dim lMidiAPIReturn As Long
Dim tone As Integer
Dim mlmidiouthandle As Long
Dim volume As Long
Dim channel As Long
mlmidiouthandle = 0
lMidiAPIReturn = midiOutOpen(mlmidiouthandle, -1, 0, 0, 0)
tone = 60
volume = 90
channel = 0
lMidiAPIReturn = midiOutShortMsg(mlmidiouthandle, &H90 + ((tone) * &H100) + (volume * &H10000) + channel)
Sleep 1000
midiOutClose mlmidiouthandle
End Sub
Option Explicit
Private Declare Function midiOutClose Lib "winmm.dll" (ByVal hMidiOut As Long) As Long
Private Declare Function midiOutOpen Lib "winmm.dll" (lphMidiOut As Long, ByVal uDeviceID As Long, ByVal dwCallback As Long, ByVal dwInstance As Long, ByVal dwFlags As Long) As Long
Private Declare Function midiOutShortMsg Lib "winmm.dll" (ByVal hMidiOut As Long, ByVal dwMsg As Long) As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Dim notes(1 To 8, 1 To 2) As Variant
Dim i, j, k, s(8) As Integer
Dim cf As Boolean
Private Sub Form_Load()
notes(1, 1) = "C4": notes(1, 2) = 60
notes(2, 1) = "D4": notes(2, 2) = 62
notes(3, 1) = "E4": notes(3, 2) = 64
notes(4, 1) = "F4": notes(4, 2) = 65
notes(5, 1) = "G4": notes(5, 2) = 67
notes(6, 1) = "A5": notes(6, 2) = 69
notes(7, 1) = "B5": notes(7, 2) = 71
notes(8, 1) = "C5": notes(8, 2) = 72
End Sub
Private Sub Command2_Click()
Dim lMidiAPIReturn As Long
Dim tone As Integer
Dim mlmidiouthandle As Long
Dim volume As Long
Dim channel As Long
Dim i As Integer
mlmidiouthandle = 0
lMidiAPIReturn = midiOutOpen(mlmidiouthandle, -1, 0, 0, 0)
volume = 90
channel = 0
i = 1
Text1.Text = ""
Do While i <= 8 '第一层循环,用于取8个数
cf = False '是否取到了重复的数
Randomize
k = Int(Rnd() * 8) + 1 '获取随机数
For j = 1 To i '第二层循环,判断是否取到的数字发生了重复
If k = s(j) Then '当发生重复的时候标记cf变量
cf = True
Exit For
End If
Next
If cf = False Then '如果取得数字没有重复,进行赋值,并显示在text1文本框
'Text1.Text = Text1.Text & k & Chr(13) & Chr(10)
s(i) = k
tone = notes(k, 2)
'MsgBox tone
lMidiAPIReturn = midiOutShortMsg(mlmidiouthandle, &H90 + ((tone) * &H100) + (volume * &H10000) + channel)
Sleep 100
'MsgBox (s(i))
Text1.Text = Text1.Text + Str(s(i))
i = i + 1 '继续取下一个数字,直到i=8
End If
Loop
End Sub
midiOutClose mlmidiouthandle
lMidiAPIReturn = midiOutClose(mlmidiouthandle)
当我按Command2达到十多次时(比如11次或16次不等),就不出声了,最后一次出声时还会拖长声音,我每次都是等最后的声响完才又按的,是不是还得加什么语句?
请大师们斧正!Option Explicit
Private Declare Function midiOutClose Lib "winmm.dll" (ByVal hMidiOut As Long) As Long
Private Declare Function midiOutOpen Lib "winmm.dll" (lphMidiOut As Long, ByVal uDeviceID As Long, ByVal dwCallback As Long, ByVal dwInstance As Long, ByVal dwFlags As Long) As Long
Private Declare Function midiOutShortMsg Lib "winmm.dll" (ByVal hMidiOut As Long, ByVal dwMsg As Long) As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Dim notes(1 To 8, 1 To 2) As Variant
Dim i, j, k, s(8) As Integer
Dim cf As Boolean
Private Sub Form_Load()
notes(1, 1) = "C4": notes(1, 2) = 60
notes(2, 1) = "D4": notes(2, 2) = 62
notes(3, 1) = "E4": notes(3, 2) = 64
notes(4, 1) = "F4": notes(4, 2) = 65
notes(5, 1) = "G4": notes(5, 2) = 67
notes(6, 1) = "A5": notes(6, 2) = 69
notes(7, 1) = "B5": notes(7, 2) = 71
notes(8, 1) = "C5": notes(8, 2) = 72
End Sub
Private Sub Command2_Click()
Dim lMidiAPIReturn As Long
Dim tone As Integer
Dim mlmidiouthandle As Long
Dim volume As Long
Dim channel As Long
Dim i As Integer
mlmidiouthandle = 0
lMidiAPIReturn = midiOutOpen(mlmidiouthandle, -1, 0, 0, 0)
volume = 90
channel = 0
i = 1
Text1.Text = ""
Do While i <= 8 '第一层循环,用于取8个数
cf = False '是否取到了重复的数
Randomize
k = Int(Rnd() * 8) + 1 '获取随机数
For j = 1 To i '第二层循环,判断是否取到的数字发生了重复
If k = s(j) Then '当发生重复的时候标记cf变量
cf = True
Exit For
End If
Next
If cf = False Then '如果取得数字没有重复,进行赋值,并显示在text1文本框
'Text1.Text = Text1.Text & k & Chr(13) & Chr(10)
s(i) = k
tone = notes(k, 2)
'MsgBox tone
lMidiAPIReturn = midiOutShortMsg(mlmidiouthandle, &H90 + ((tone) * &H100) + (volume * &H10000) + channel)
Sleep 100
'MsgBox (s(i))
Text1.Text = Text1.Text + Str(s(i))
i = i + 1 '继续取下一个数字,直到i=8
End If
DoEvents
Loop
lMidiAPIReturn = midiOutClose(mlmidiouthandle)
End Sub
Option Explicit
Private Declare Function midiOutClose Lib "winmm.dll" (ByVal hMidiOut As Long) As Long
Private Declare Function midiOutOpen Lib "winmm.dll" (lphMidiOut As Long, ByVal uDeviceID As Long, ByVal dwCallback As Long, ByVal dwInstance As Long, ByVal dwFlags As Long) As Long
Private Declare Function midiOutShortMsg Lib "winmm.dll" (ByVal hMidiOut As Long, ByVal dwMsg As Long) As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Dim notes(1 To 8, 1 To 2) As Variant
Dim i, j, k, s(8) As Integer
Dim cf As Boolean
Private Sub Form_Load()
notes(1, 1) = "C4": notes(1, 2) = 60
notes(2, 1) = "D4": notes(2, 2) = 62
notes(3, 1) = "E4": notes(3, 2) = 64
notes(4, 1) = "F4": notes(4, 2) = 65
notes(5, 1) = "G4": notes(5, 2) = 67
notes(6, 1) = "A5": notes(6, 2) = 69
notes(7, 1) = "B5": notes(7, 2) = 71
notes(8, 1) = "C5": notes(8, 2) = 72
End Sub
Private Sub Command2_Click()
Dim lMidiAPIReturn As Long
Dim tone As Integer
Dim mlmidiouthandle As Long
Dim volume As Long
Dim channel As Long
Dim i As Integer
mlmidiouthandle = 0
lMidiAPIReturn = midiOutOpen(mlmidiouthandle, -1, 0, 0, 0)
volume = 90
channel = 0
i = 1
Text1.Text = ""
Do While i <= 8 '第一层循环,用于取8个数
cf = False '是否取到了重复的数
Randomize
k = Int(Rnd() * 8) + 1 '获取随机数
For j = 1 To i '第二层循环,判断是否取到的数字发生了重复
If k = s(j) Then '当发生重复的时候标记cf变量
cf = True
Exit For
End If
Next
If cf = False Then '如果取得数字没有重复,进行赋值,并显示在text1文本框
'Text1.Text = Text1.Text & k & Chr(13) & Chr(10)
s(i) = k
tone = notes(k, 2)
'MsgBox tone
lMidiAPIReturn = midiOutShortMsg(mlmidiouthandle, &H90 + ((tone) * &H100) + (volume * &H10000) + channel)
Sleep 100
'MsgBox (s(i))
Text1.Text = Text1.Text + Str(s(i))
i = i + 1 '继续取下一个数字,直到i=8
End If
DoEvents
Loop
lMidiAPIReturn = midiOutClose(mlmidiouthandle)
End Sub
Private Declare Function midiOutClose Lib "winmm.dll" (ByVal hMidiOut As Long) As Long
Private Declare Function midiOutOpen Lib "winmm.dll" (lphMidiOut As Long, ByVal uDeviceID As Long, ByVal dwCallback As Long, ByVal dwInstance As Long, ByVal dwFlags As Long) As Long
Private Declare Function midiOutShortMsg Lib "winmm.dll" (ByVal hMidiOut As Long, ByVal dwMsg As Long) As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
'--------------------------------------------------------
Dim notes(1 To 8, 1 To 2) As Variant
'--------------------------------------------------------
Private Sub Form_Load()
Randomize '此语句应在初始化时调用一次即可
notes(1, 1) = "C4": notes(1, 2) = 60
notes(2, 1) = "D4": notes(2, 2) = 62
notes(3, 1) = "E4": notes(3, 2) = 64
notes(4, 1) = "F4": notes(4, 2) = 65
notes(5, 1) = "G4": notes(5, 2) = 67
notes(6, 1) = "A5": notes(6, 2) = 69
notes(7, 1) = "B5": notes(7, 2) = 71
notes(8, 1) = "C5": notes(8, 2) = 72
End Sub
'--------------------------------------------------------
Private Sub Command2_Click()
Dim lMidiAPIReturn As Long
Dim tone As Integer
Dim mlmidiouthandle As Long
Dim volume As Long
Dim channel As Long
Dim i As Integer
Dim a As Integer
Dim b As Integer
Dim t As Integer
Dim s(8) As Integer
For i = 1 To 8
s(i) = i
Next '随机打乱s(i)的顺序 即洗牌
For i = 8 To 2 Step -1
a = i: b = Int(Rnd() * i) + 1
If a <> b Then
t = s(a): s(a) = s(b): s(b) = t
End If
Next mlmidiouthandle = 0
lMidiAPIReturn = midiOutOpen(mlmidiouthandle, -1, 0, 0, 0)
volume = 90
channel = 0 Text1.Text = ""
For i = 1 To 8
Text1.Text = Text1.Text + CStr(s(i)) + " " + notes(s(i), 1) + ", "
Text1.Refresh
tone = notes(s(i), 2)
lMidiAPIReturn = midiOutShortMsg(mlmidiouthandle, &H90 + ((tone) * &H100) + (volume * &H10000) + channel)
Sleep 100
Next lMidiAPIReturn = midiOutClose(mlmidiouthandle)
End Sub
我也有些关于Midi的问题请教:
1. 通过以上讨论,使用midiOutShortMsg控制 音色(乐器)、音符(频率)、音量(声强度)的问题已经解决,但发生的长度是如何确定的?如何控制?
2. Midi文件的文件格式如何?哪里有较详细的官方的说明?
3. 有能将midi文件打开转换成简谱 和 编辑简谱并能存为midi 的源程序吗?请好心人能把对我的帮助发到 ,我很少上网,怕找不到这里了,谢谢!