从C#中的MIDI端口获取信号

时间:2010-01-02 10:12:17

标签: c# midi

我为我的生日买了一个MIDI键盘。我找到了一个程序(MidiPiano),它从MIDI输入中获取信号并将其转换为音乐,但我更愿意自己写一个。

我在哪里可以找到执行此类任务的文档? MIDI协议有很好的记录,但不是MIDI端口。

我从CodeProject(Project MIDI和C#MIDI Toolkit)检查了两个项目,但是花了很多时间没有接近我的目标。

对项目的引用会很好,但是请只有C#。

6 个答案:

答案 0 :(得分:6)

您需要包含http://msdn.microsoft.com/en-us/library/dd757277(VS.85).aspx

中列出的所有必需功能

如果您只是使用短消息并不太难,如果您想要进行SysEx或输出流式传输,事情就会变得更复杂。

基本输入所需的全部端口是获取有效的输入ID(InputCount -1),传递有效的ID以打开,启动输入,通过委托接收消息...停止输入然后最后关闭它。这是一个非常粗略的示例,说明如何实现这一点 - 您需要进行一些检查,并注意在关闭之前未收集端口并且已关闭回调或您将冻结系统!

祝你好运!

namespace MIDI
{
    public class InputPort
    {
        private NativeMethods.MidiInProc midiInProc;
        private IntPtr handle;

        public InputPort()
        {
            midiInProc = new NativeMethods.MidiInProc(MidiProc);
            handle = IntPtr.Zero;
        }

        public static int InputCount
        {
            get { return NativeMethods.midiInGetNumDevs(); }
        }

        public bool Close()
        {
            bool result = NativeMethods.midiInClose(handle) 
                == NativeMethods.MMSYSERR_NOERROR;
            handle = IntPtr.Zero;
            return result;
        }

        public bool Open(int id)
        {
            return NativeMethods.midiInOpen(
                out handle,
                id,
                midiInProc,
                IntPtr.Zero,
                NativeMethods.CALLBACK_FUNCTION)
                    == NativeMethods.MMSYSERR_NOERROR;
        }

        public bool Start()
        {
            return NativeMethods.midiInStart(handle)
                == NativeMethods.MMSYSERR_NOERROR;
        }

        public bool Stop()
        {
            return NativeMethods.midiInStop(handle)
                == NativeMethods.MMSYSERR_NOERROR;
        }

        private void MidiProc(IntPtr hMidiIn,
            int wMsg,
            IntPtr dwInstance,
            int dwParam1,
            int dwParam2)
        {
            // Receive messages here
        }
    }

    internal static class NativeMethods
    {
        internal const int MMSYSERR_NOERROR = 0;
        internal const int CALLBACK_FUNCTION = 0x00030000;

        internal delegate void MidiInProc(
            IntPtr hMidiIn,
            int wMsg,
            IntPtr dwInstance,
            int dwParam1,
            int dwParam2);

        [DllImport("winmm.dll")]
        internal static extern int midiInGetNumDevs();

        [DllImport("winmm.dll")]
        internal static extern int midiInClose(
            IntPtr hMidiIn);

        [DllImport("winmm.dll")]
        internal static extern int midiInOpen(
            out IntPtr lphMidiIn,
            int uDeviceID,
            MidiInProc dwCallback,
            IntPtr dwCallbackInstance,
            int dwFlags);

        [DllImport("winmm.dll")]
        internal static extern int midiInStart(
            IntPtr hMidiIn);

        [DllImport("winmm.dll")]
        internal static extern int midiInStop(
            IntPtr hMidiIn);
    }
}

答案 1 :(得分:2)

我也找不到多少,但就像Josh说的那样,Carl肯定在MIDI上做过相当多的工作,所以也许给他一个电子邮件......他甚至可以回复,但他通常是VB.Net除非有人将他的东西移植到C#,否则这个人呢?

对于一些看起来很有希望的其他参考资料......

如果您正在寻找纯粹的C#解决方案......请查看Alvas.Audio。它确实看起来有点高端,但可能会有所帮助。

也许project midi

答案 2 :(得分:2)

我正在开发c#midi通信系统的过程。 Sanford的midi工具包很好,但Leslie的实现有许多改进,使代码的可读性降低。我的代码尽可能简单。如果你想要你可以加入我。几天后,我发布了完全工作的midi监视器。只需查看http://puremidi.codeplex.com/

即可

答案 3 :(得分:1)

使用C#Midi Toolkit从键盘接收midi信息(连接到音频卡的midi输入端口)。要创建音频(音乐或音调),您需要生成连续的数字音频数据流。您可以从C#Synth Toolkit(与midi工具包相同的作者)开始编写您自己的合成器。

但你也可以下载一个免费的(开源)音序器程序(例如大胆)并使用VST乐器插件为你完成这项工作。网上有很多免费插件。

答案 4 :(得分:0)

我已经通过编写Python脚本来解决这个问题,每次在MIDI键盘上发生音符开/关时都会发送UDP数据包。

MIDI over TCP/IP/UDP to be received inUnity3D with C#/.NET

这样平台特定的MIDI内容被包装,我可以编写平台无关的C#代码来获取UDP数据包。

答案 5 :(得分:0)

使用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}");
        }
    }
}

您可以在库文档的Devices部分中找到更多信息。