继续,前面已经实现了C#调用Windows API实现了弹出对话框功能。使用了User32.dll文件,主要代码如下:

[DllImport("User32.dll")]
public static extern int MessageBox(int h, string m, string c, int type);
详情请参考:http://hovertree.com/h/bjaf/psjdasa2.htm

效果如下:

也练习了调用winmm.dll播放wav声音文件,主要代码:
[DllImport("winmm.dll")]
private static extern int sndPlaySoundA(byte[] lpszSoundName, int uFlags);

详情参考:http://hovertree.com/h/bjaf/jeg0ytf5.htm

效果图:

接下来继续练习调用别API,就调用winmm.dll的midi播放功能吧。

MIDI(Musical Instrument Digital Interface)乐器数字接口 ,是20 世纪80 年代初为解决电声乐器之间的通信问题而提出的。MIDI是编曲界最广泛的音乐标准格式,可称为“计算机能理解的乐谱”。它用音符的数字控制信号来记录音乐。一首完整的MIDI音乐只有几十KB大,而能包含数十条音乐轨道。几乎所有的现代音乐都是用MIDI加上音色库来制作合成的。MIDI 传输的不是声音信号, 而是音符、控制参数等指令, 它指示MIDI 设备要做什么,怎么做, 如演奏哪个音符、多大音量等。它们被统一表示成MIDI 消息(MIDI Message) 。传输时采用异步串行通信, 标准通信波特率为31.25×( 1±0.01) KBaud。

所以调用API播放midi也是按照格式指定播放指令。接下来就测试实现midi功能。

首先是打开midi输出设备的API:
MMRESULT midiOutOpen(
LPHMIDIOUT lphmo,
UINT uDeviceID,
DWORD_PTR dwCallback,
DWORD_PTR dwCallbackInstance,
DWORD dwFlags
);
详情请看:http://hovertree.com/h/bjaf/tug59e9l.htm

在C#中调用该API:
[DllImport("winmm.dll")]
private static extern UInt32 midiOutOpen(out UInt32 lphMidiOut, uint uDeviceID, UInt32 dwCallback, UInt32 dwInstance, UInt32 dwFlags);

其中lphMidiOut 为设备的句柄 ,在后面播放声音会用到。

然后是向设备发送播放指令API:
MMRESULT midiOutShortMsg(
HMIDIOUT hmo,
DWORD dwMsg
);
详情请参考:http://hovertree.com/h/bjaf/4ext7m8l.htm

在C#中调用:
[DllImport("winmm.dll")]
private static extern UInt32 midiOutShortMsg(UInt32 hMidiOut, UInt32 dwMsg);

这里hMidiOut就是midiOutOpen方法的lphMidiOut
接下来就封装这些API,Midi输出设备需要打开后才能播放声音,在封装的类HewenqiMidi中加一个状态,表示设备是否打开,代码为:private bool _isOpened; 因为是调用API,所以设备有一个句柄,也就是上面提到的lphMidiOut ,所以类中加一个设备句柄字段,句柄的类型为32位无符号整形UNIT,参考:http://hovertree.com/h/bjaf/exee7473.htm,代码为:private uint _deviceHandle; 用来存储midiOutOpen获得的句柄lphMidiOut,这两个字段可以封装为属性,只读的属性。

接下来,实现设备的打开功能,主要代码:
uint h_Device;
uint h_r = midiOutOpen(out h_Device, 0, 0, 0, 0);
当h_r等与0时,表示打开成功,否则打开不成功,具体返回值可以参考:http://hovertree.com/h/bjaf/tug59e9l.htm

播放声音的方法:
public uint ShortPlay(uint msg)
{
if (_isOpened)
return midiOutShortMsg(_deviceHandle, msg);
else
return 621;
}
先检查设备是否已经打开,打开了就播放声音,返回0表示成功。参考:http://hovertree.com/h/bjaf/37iovb7c.htm

参数msg表示要播放的声音,这个参数可以包含音量和音高等信息,详情请参考:
http://hovertree.com/h/bjaf/4ext7m8l.htm
根据这个参数构造以下方法:

/// <summary>
/// 播放声音
/// </summary>
/// <param name="key">音高(音调)</param>
/// <param name="volume">音量</param>
/// <param name="chenel">通道</param>
/// <returns></returns>
public uint ShortPlay(uint key, uint volume, uint chenel)
{
return ShortPlay(144 + key * 256 + volume * 65536 + chenel);
}

这样就可以方便调节播放的音量和音高了。当然还有可以设置音色,先放到后边介绍。

打开MIDI设备后,要怎么关闭呢?也是调用API:
midiOutClose(
hMidiOut: HMIDIOUT {设备句柄}
)
详情:http://hovertree.com/h/bjaf/gmn82vlo.htm

在C#中调用:
[DllImport("winmm.dll")]
private static extern UInt32 midiOutClose(UInt32 hMidiOut);
返回0表示成功

接着,使用HewenqiMidi 类,建立一个WinForm 窗体,测试播放功能。如下图所示:

演示下载地址:http://hovertree.com/h/bjaf/xy6rbg5m.htm

源码发布到这个网址:http://hovertree.net/

转自:http://hovertree.com/h/bjaf/dg7nbe4t.htm

最新文章

  1. jQuery.rotate.js参数
  2. hibernate笔记--组件映射方法
  3. Android UI 之实现多级列表TreeView
  4. jQuery小节
  5. MySql安装与MySQL添加用户、删除用户与授权
  6. Linux Running State Process &quot;.so&quot;、&quot;code&quot; Injection Technology
  7. setAttribute()和getAttibute(),getParameter()
  8. 转发离线安装 Android Studio 更新
  9. javascript获取随机rgb颜色和十六进制颜色的方法
  10. 一种基于PTP 协议的局域网高精度时钟同步方法(转)
  11. Javascript原型链
  12. taglist
  13. 自定义控件:抽屉SlidingDrawer——wrap_content非全屏
  14. (转)Qt Model/View 学习笔记 (三)——Model类
  15. IOS-CGAffineTransformMake 矩阵变换 的运算原理
  16. 关于LEA指令(单周期就可以做简单的算术计算)
  17. (转)安装 Apache 出现 &lt;OS 10013&gt; 以一种访问权限不允许的方式做了一个访问套接字的尝试
  18. Composer 基本指令操作使用
  19. ARXObject的入门学习
  20. Java: 分解List&lt;HashMap&lt;String, String&gt;&gt;

热门文章

  1. Android实现TCP断点上传,后台C#服务实现接收
  2. 免费道路 bzoj 3624
  3. 深入理解css3中nth-child和 nth-of-type的区别
  4. 【干货分享】流程DEMO-资产请购单
  5. Ubuntu安装redis并配置远程、密码以及开启php扩展
  6. [故障公告]受阿里云部分ECS服务器故障影响,目前无法上传图片与文件
  7. innerHTML和innerText的区别
  8. Protobuf使用规范分享
  9. clearfix的最佳方案----在路上(22)
  10. Linux进程管理及while循环