加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

MIDI API(一)编程方法

(2015-10-30 21:02:33)
标签:

多媒体

分类: 编程

http://blog.163.com/zom1995@126/blog/static/1680961322015723403380/

一、API声明

  如果声明为Public则需要写到模块中,否则改为Private

Public 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

Public Declare Function midiOutClose Lib "winmm.dll" (ByVal hMidiOut As Long) As Long

Public Declare Function midiOutShortMsg Lib "winmm.dll" (ByVal hMidiOut As Long, ByVal dwMsg As Long) As Long

Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

  这里面涉及到打开和关闭,分别是midiOutOpen和midiOutClose,必须先使用midiOutOpen然后才能调用midiOutShortMsg。调用后应立即调用midiOutClose关闭。否则,VB会重启。

  Sleep的作用是控制时间。除外,还需要声明一个Long类型的变量作为midiOutOpen、midiOutClose、midiOutShortMsg函数的第一个参数。

二、实例

  比如单击Command1发出一个长为1s,音量为80的C4音,则有如下代码:

Dim hMidiOut

Private Sub Command1_Click()

    Dim Vol, Pitch, Channel As Byte

    midiOutOpen hMidiOut, -1, 0, 0, 0

    midiOutShortMsg hMidiOut, &HC0 + (0 * &H100) + 0   '参数:&HC0 + 音色表的值 * &H100 + 通道值

    Pitch = 60        ' C4,相邻的值是半音

    Vol = 80          ' 音量80

    Channel = 0      ' 通道0~15,值为9是Percussion专用的,在设置音色之前除了值为9,其他默认为钢琴

    midiOutShortMsg hMidiOut, &H90 (Pitch * &H100) + (Vol * &H10000) + Channel

    Sleep 1000        '持续1s

    midiOutClose hMidiOut

End Sub

  如果放不出来声音,就想办法把midiOutOpen的返回值显示出来,值为0则正常。如果返回值是4,重启VB。

三、midiOutShortMsg的用法

1、换乐器:midiOutShortMsg hMidiOut, &HC0 + (Patch * &H100) + Channel

2、发送音符:midiOutShortMsg hMidiOut, &H90 + (Pitch * &H100) + (Volume * &H10000) + Channel

3、关闭音符:midiOutShortMsg hMidiOut, &H80 + (Pitch * &H100) + (Volume * &H10000) + Channel

  hMidiOut指的是上面的Long类型变量;Patch是乐器,范围是0~127;Channel是通道,一个通道只能用一种乐器,一共16个通道;Pitch是音高,60是C4,61是C#4,相邻的是半音。

  关闭音符也是很重要的,如果代码里面没有任何关闭音符的语句,那么就和加了延音踏板差不多。

四、连奏

  声明一个Byte类型的一维数组,存放音高,然后用for循环依次发送。比如依次播放C4,D4,E4,F4,G4,A4,B4,C5。有如下代码:

Dim hMidi

Private Sub Command1_Click()

    Dim i As Integer

    Dim p(0 To 7) As Integer

    p(0) = 60

    p(1) = 62

    p(2) = 64

    p(3) = 65

    p(4) = 67

    p(5) = 69

    p(6) = 71

    p(7) = 72

    hMidi = 0

    ret = midiOutOpen(hMidi, -1, 0, 0, 0)

    midiOutShortMsg hMidi, (&HC0 + 0 * &H100) + 0       '发送改变乐器

    patch = 60

    vol = 80

    channel = 0

    For i = 0 To 7

        midiOutShortMsg hMidi, &H90 + (p(i) * &H100) + (vol * &H10000) + channel   '发送音符

        Sleep 1000

        midiOutShortMsg hMidi, &H80 + (p(i) * &H100) + channel

    Next

    midiOutClose hMidi

End Sub

  然后运行程序,单击Command1,就知道效果了

五、同时发送音符

  如果是用数组,那就也可以用for循环,然后把Sleep放到Next的后面。或者,不用数组一行一行写。比如:

Private Sub Command2_Click()

    ret = midiOutOpen(hMidi, -1, 0, 0, 0)

    midiOutShortMsg hMidi, (&HC0 + 0 * &H100) + 0

    vol = 80

    channel = 0

    midiOutShortMsg hMidi, &H90 + (60 * &H100) + (vol * &H10000) + channel

    midiOutShortMsg hMidi, &H90 + (64 * &H100) + (vol * &H10000) + channel

    Sleep 1000

    midiOutClose hMidi

End Sub

七、琶音

  假设两个或多个音符,在midiOutShortMsg之间使用Sleep语句,后面的数值不能太大也不能太小,比如:

Private Sub Command4_Click()
    ret = midiOutOpen(hMidi, -1, 0, 0, 0)
    midiOutShortMsg hMidi, (&HC0 + 0 * &H100) + 0
    vol = 80
    channel = 0
    midiOutShortMsg hMidi, &H90 + (60 * &H100) + (vol * &H10000) + channel
    Sleep 50
    midiOutShortMsg hMidi, &H90 + (64 * &H100) + (vol * &H10000) + channel
    Sleep 50
    midiOutShortMsg hMidi, &H90 + (67 * &H100) + (vol * &H10000) + channel
    Sleep 1000
    midiOutClose hMidi

End Sub

八、非连奏

  在中途关闭音符,比如:
Private Sub Command4_Click()
    ret = midiOutOpen(hMidi, -1, 0, 0, 0)
    midiOutShortMsg hMidi, (&HC0 + 0 * &H100) + 0
    vol = 80
    channel = 0
    midiOutShortMsg hMidi, &H90 + (60 * &H100) + (vol * &H10000) + channel
    Sleep 100
    midiOutShortMsg hMidi, &H80 + (60 * &H100) + (vol * &H10000) + channel
    Sleep 1000
    midiOutShortMsg hMidi, &H90 + (67 * &H100) + (vol * &H10000) + channel
    Sleep 1000
    midiOutClose hMidi

End Sub

九、速度和时值

  如果节拍是4/4,速度是120bpm,那么四分音符的时值是120/60=2s,也就是2000毫秒,而Sleep的参数就是用毫秒作为单位的。这样我们就能算出全音符,二分音符,八分音符等等的时值了。

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有