我为我的生日买了一个 MIDI 键盘。我找到了一个程序(MidiPiano),它从 MIDI 输入中获取信号并将其转换为音乐,但我更愿意自己编写一个。
我在哪里可以找到执行此类任务的文档?MIDI 协议有据可查,但 MIDI 端口却没有。
我检查了 CodeProject 中的两个项目(Project MIDI 和 C# MIDI Toolkit),但花了很多时间都没有接近我的目标。
对项目的引用会很好,但请仅使用 C#。
您需要包装http://msdn.microsoft.com/en-us/library/dd757277(VS.85).aspx中列出的所有所需功能
如果您只是使用短消息,这并不太难,如果您想做 SysEx 或输出流,事情会变得有点复杂。
基本输入端口所需要做的就是获取有效的输入 ID (InputCount -1),将有效的 ID 传递给 Open,启动输入,通过委托接收消息...停止输入,然后最后关闭它。这是一个非常粗略的示例,说明如何实现这一点 - 您需要进行一些检查并注意端口在关闭之前没有被收集,并且关闭的回调已经发生,否则您将冻结您的系统!
祝你好运!
命名空间 MIDI { 公共类输入端口 { 私有 NativeMethods.MidiInProc midiInProc; 私有 IntPtr 句柄; 公共输入端口() { midiInProc = new NativeMethods.MidiInProc(MidiProc); 句柄 = IntPtr.Zero; } 公共静态 int InputCount { 获取 { 返回 NativeMethods.midiInGetNumDevs(); } } 公共布尔关闭() { 布尔结果 = NativeMethods.midiInClose(handle) == NativeMethods.MMSYSERR_NOERROR; 句柄 = IntPtr.Zero; 返回结果; } 公共布尔打开(int id) { 返回 NativeMethods.midiInOpen( 出手柄, ID, midiInProc, IntPtr. 零, NativeMethods.CALLBACK_FUNCTION) == NativeMethods.MMSYSERR_NOERROR; } 公共布尔开始() { 返回 NativeMethods.midiInStart(句柄) == NativeMethods.MMSYSERR_NOERROR; } 公共布尔停止() { 返回 NativeMethods.midiInStop(句柄) == NativeMethods.MMSYSERR_NOERROR; } 私人无效MidiProc(IntPtr hMidiIn, 诠释 wMsg, IntPtr dwInstance, int dwParam1, int dwParam2) { // 在这里接收消息 } } 内部静态类 NativeMethods { 内部常量 int MMSYSERR_NOERROR = 0; 内部常量 int CALLBACK_FUNCTION = 0x00030000; 内部委托无效 MidiInProc( IntPtr hMidiIn, 诠释 wMsg, IntPtr dwInstance, int dwParam1, int dwParam2); [DLLImport("winmm.dll")] 内部静态外部 int midiInGetNumDevs(); [DLLImport("winmm.dll")] 内部静态外部 int midiInClose( IntPtr hMidiIn); [DLLImport("winmm.dll")] 内部静态外部 int midiInOpen( 出 IntPtr lphMidiIn, int uDeviceID, MidiInProc dwCallback, IntPtr dwCallbackInstance, int dwFlags); [DLLImport("winmm.dll")] 内部静态外部 int midiInStart( IntPtr hMidiIn); [DLLImport("winmm.dll")] 内部静态外部 int midiInStop( IntPtr hMidiIn); } }
我也找不到太多,但就像 Josh 说的,Carl 确实在 MIDI 方面做了很多工作,所以也许给他发一封电子邮件……他甚至可以回复,但他通常是 VB.Net 人,所以除非有人将他的东西移植到 C#?
对于其他一些看起来很有希望的参考资料......
如果您正在寻找纯 C# 解决方案……请查看Alvas.Audio。对于您的要求,它看起来确实有点高端,但可能会有所帮助。
也可能是项目midi
我只是在 c# midi 通信系统的开发过程中。Sanford 的 midi 工具包很好,但 Leslie 的实现有很多改进,这使得代码的可读性降低。我的代码尽可能简单。如果你愿意,可以加入我。几天后,我发布了完全工作的 MIDI 监视器。看看http://puremidi.codeplex.com/
使用 C# Midi Toolkit 从键盘接收 midi 信息(连接到声卡的 midi 输入端口)。要创建音频(音乐或音调),您需要生成连续的数字音频数据流。您可以从 C# Synth Toolkit(与 midi 工具包的作者相同)开始编写您自己的合成器。
但您也可以下载免费(开源)音序器程序(例如 Audacity)并使用 VST 乐器插件为您完成这项工作。网络上有很多免费的插件。
我已经通过编写 Python 脚本以在 MIDI 键盘上每次出现音符 ON/OFF 时传输 UDP 数据包的方式解决了这个问题。
使用 C#/.NET 在 Unity3D 中接收 TCP/IP/UDP 上的 MIDI
这样,平台特定的 MIDI 内容就被包装了,我可以编写与平台无关的 C# 代码来获取 UDP 数据包。
使用DryWetMIDI,您可以使用以下代码从 MIDI 端口获取事件:
namespace InputDeviceExample
{
class Program
{
private static IInputDevice _inputDevice;
static void Main(string[] args)
{
_inputDevice = InputDevice.GetByName("Some MIDI device");
_inputDevice.EventReceived += OnEventReceived;
_inputDevice.StartEventsListening();
Console.WriteLine("Input device is listening for events. Press any key to exit...");
Console.ReadKey();
(_inputDevice as IDisposable)?.Dispose();
}
private static void OnEventReceived(object sender, MidiEventReceivedEventArgs e)
{
var midiDevice = (MidiDevice)sender;
Console.WriteLine($"Event received from '{midiDevice.Name}' at {DateTime.Now}: {e.Event}");
}
}
}
您可以在库文档的设备部分找到更多信息。