这一篇介绍向声卡发送数据的方法。首先在C#中重写midiOutOpen和midiOutShortMsg方法:
//打开指定的MIDI输出设备进行回放
[DllImport("winmm.dll")]
public static extern uint midiOutOpen(out IntPtr lphMidiOut, uint uDeviceID, IntPtr dwCallback, IntPtr dwInstance, uint dwFlags);
//向指定的MIDI输出设备发送一条短MIDI消息
[DllImport("winmm.dll")]
public static extern uint midiOutShortMsg(IntPtr hMidiOut, uint dwMsg);
GM音色表:http://www2.gxai.edu.cn/dnyy/dnzp/ShowArticle.asp?ArticleID=488 ,声卡也可以模拟此声色表中的声音进行演奏,操作流程如下:
midiOutOpen(out handle, 0, IntPtr.Zero, IntPtr.Zero, 0); //打开设备,获取handle
midiOutShortMsg(handle, Convert.ToUInt32(0x000000C0 + 音色值 * 256)); //设置音色,音色值通过GM音色表可以查到,例如:73是短笛
midiOutShortMsg(handle, Convert.ToUInt32(0x00403B90 + data * 256)); //给声卡发送数据,播放声音,midiOutShortMsg参数如下:
来自百度百科:http://baike.baidu.com/view/2089748.htm
3、使用格式:
ret=midiOutShortMsg(midiout, &H90 + ((flip) * &H100) + (volume * &H10000) + channel)
说明:
midiout是midioutopen开启设备成功后就会提供这个Long型变量,flip是Integer型参数,代表音的高低,相邻为半音,如60和61,隔1为全音,如63和65;volume为设备的音量值,普遍使用的是0-100之间的值。channel为通道,默认使用0即可。所谓通道就是MIDI音乐中的音层,就像电子琴的16个音层,有节奏通道,和弦通道,低音通道等等。最大可以支持16层,可以取其任意一个值即可。
将以上步骤封装在一个函数中,如下:
private void playNote(IntPtr handle, uint data, int time)
{
Audio.midiOutShortMsg(handle, Convert.ToUInt32(0x000000C0 + comboBox1.SelectedIndex * 256));
if (data == 0)
{
System.Threading.Thread.Sleep(time);
return;
}
Audio.midiOutShortMsg(handle, Convert.ToUInt32(0x00403B90 + data * 256));
System.Threading.Thread.Sleep(time);
Audio.midiOutReset(handle);
}//combobox1是音色的下拉列表,data是基于3B的音阶
通过以上函数,执行下列代码,即可播放98笑傲江湖(吕颂贤)中的音调。
private void btnSample_Click(object sender, EventArgs e)
{
playNote(handle, 12, 250);
playNote(handle, 12, 250);
playNote(handle, 15, 250);
playNote(handle, 17, 250);
playNote(handle, 19, 1000);
playNote(handle, 24, 700);
playNote(handle, 19, 250);
playNote(handle, 22, 200);
playNote(handle, 00, 250);
playNote(handle, 22, 900);
playNote(handle, 19, 400);
playNote(handle, 17, 400);
playNote(handle, 19, 400);
playNote(handle, 22, 400);
playNote(handle, 24, 250);
playNote(handle, 22, 250);
playNote(handle, 19, 1500);
playNote(handle, 00, 300);
playNote(handle, 19, 1000);
playNote(handle, 24, 700);
playNote(handle, 19, 250);
playNote(handle, 22, 200);
playNote(handle, 00, 250);
playNote(handle, 22, 900);
playNote(handle, 19, 400);
playNote(handle, 17, 400);
playNote(handle, 19, 400);
playNote(handle, 22, 400);
playNote(handle, 24, 250);
playNote(handle, 22, 250);
playNote(handle, 19, 1000);
playNote(handle, 00, 300);
playNote(handle, 19, 400);
playNote(handle, 17, 250);
playNote(handle, 15, 600);
playNote(handle, 00, 100);
playNote(handle, 15, 250);
playNote(handle, 17, 400);
playNote(handle, 19, 400);
playNote(handle, 17, 100);
playNote(handle, 00, 250);
playNote(handle, 17, 500);
playNote(handle, 00, 100);
playNote(handle, 17, 400);
playNote(handle, 15, 250);
playNote(handle, 12, 250);
playNote(handle, 00, 100);
playNote(handle, 12, 250);
playNote(handle, 15, 250);
playNote(handle, 17, 400);
playNote(handle, 19, 400);
playNote(handle, 22, 600);
playNote(handle, 24, 250);
playNote(handle, 22, 400);
playNote(handle, 19, 250);
playNote(handle, 17, 250);
playNote(handle, 15, 600);
playNote(handle, 17, 600);
playNote(handle, 19, 400);
playNote(handle, 17, 150);
playNote(handle, 00, 250);
playNote(handle, 17, 600);
playNote(handle, 15, 600);
playNote(handle, 12, 300);
playNote(handle, 00, 100);
playNote(handle, 12, 250);
playNote(handle, 15, 250);
playNote(handle, 17, 250);
playNote(handle, 19, 400);
playNote(handle, 22, 250);
playNote(handle, 24, 700);
playNote(handle, 00, 100);
playNote(handle, 24, 500);
}