开发者

Getting signals from a MIDI port in C#

I bought a MIDI keyboard for my birthday. I found a program (MidiPiano) that gets signals from the MIDI input and translates it into music, but I'd rather like to write one myself.

Where can I find documentation for doing such a task?开发者_开发问答 The MIDI protocol is well documented, but not the MIDI ports.

I checked two projects from CodeProject (Project MIDI and C# MIDI Toolkit), but spent many hours without getting close to my goal.

A reference to a project will be fine, but please, only C#.


You need to wrap all the needed functions listed at http://msdn.microsoft.com/en-us/library/dd757277(VS.85).aspx

It's not too difficult if you're just using short messages, things get a little more complicated if you want to do SysEx or output streaming.

All you need for a basic input Port is to get the valid input IDs (InputCount -1), pass a valid ID to Open, Start the input, receive the messages via a delegate... Stop the input and then finally close it. This is a very rough example of how this could be acheived - you will need to do some checking and be careful that the Port isn't collected before it's closed and the closed callback has happened or you will freeze your system!

Good luck!

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);
    }
}


I'm just in developing process of c# midi communication system. Sanford's midi toolkit is good but Leslie implementation has many improvement which makes code less readable. My code is as simple as possible. If you want you can join me. In a few days I publish fully working midi monitor. Just look at http://puremidi.codeplex.com/


I couldn't find much either, but like Josh says, Carl has definitely done quite a bit of work on MIDI, so maybe give him an email... he may even reply, but he is typically a VB.Net guy so unless someone has ported his stuff to C#?

For some other references that looked promising...

If you are looking for a pure C# solution... have a look at Alvas.Audio. It does look a bit high end for what you are asking, but may be of some help.

Also maybe project midi


With DryWetMIDI you can get events from a MIDI port with this code:

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

You can find more info in the Devices section of the library docs.


Use the C# Midi Toolkit to receive the midi information from your keyboard (connected to the midi in-port of you audio card). To create audio (music or tones) you need to generate a continues stream of digital audio data. You could start with the C# Synth Toolkit (same author as the midi toolkit) to write your own synth.

But you could also download a free (open source) sequencer program (audacity for instance) and use VST instrument plugins to do the job for you. There are a lot of free plugins available on the web.


I have solved this in a roundabout way by writing a Python script to transmit a UDP packet every time a note ON/OFF occurs on the MIDI keyboard.

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

That way the platform specific MIDI stuff is wrapped, and I can write platform agnostic C# code to pick up the UDP packet.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜