C# 与电子琴交互示例(Midi通讯)

本文参考博友的文章:http://blog.csdn.net/tianjun2012/article/details/16818467

今天做了一个和Midi设备通信的例程,国内这方面资料略显缺乏,我参考了国外的一篇帖子后写成:http://stackoverflow.com/questions/1991159/getting-signals-from-a-midi-port-in-c-sharp

例程在我家的Casio ct-688上测设通过。


midi设备通讯我们不需要自己开发驱动,可以去对应设备的官网上下好windows的驱动,这样,驱动程序会自动将midi设备过来的信号,转换成符合windows的系统调用,开发者只需调windowsAPI就可以了。


具体要用的API主要有:

midiInOpen,开启一个midi设备,原型如下:

MMRESULT midiInOpen(
  LPHMIDIIN lphMidiIn,  //指向handle的指针
  UINT uDeviceID,	//设备id,可能的选择是0~总数-1,通常生成一个midi设备列表,交给用户选择,如果只有一个设备,就写0即可
  DWORD_PTR dwCallback, //消息的回调函数指针,也可以是线程的指针,窗口的指针
  DWORD_PTR dwCallbackInstance, //给回调函数传入用户附近参数的指针,不需要时可以传入null
  DWORD dwFlags		//flag,具体参见api文档
);

midiInGetNumDevs,获取当前的midi设备总数,用来判断当前是否有可用的midi设备,如果为0,则说明没有可用设备。

UINT midiInGetNumDevs(void);

MidiInProc callback function,用来获取消息的回调函数指针,原型如下

void CALLBACK MidiInProc(
  HMIDIIN hMidiIn,	//设备handle
  UINT wMsg,		//传来的消息号
  DWORD_PTR dwInstance, //用户参数指针,如果没传入一般为null
  DWORD_PTR dwParam1,	//参数1
  DWORD_PTR dwParam2	//参数2
);
具体参数的解析可以参见这篇文章:
点击打开链接

下面就附上完整的代码,因为我要做的项目是C#的,所以也用了下面的C#测试代码。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows;
using System.Runtime.InteropServices;
using System.Threading;


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,   //HMIDIIN
                id,			  //id
                midiInProc,   //CallBack
                IntPtr.Zero,  //CallBack Instance
                NativeMethods.CALLBACK_FUNCTION)  //flag
                    == 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,
            uint wMsg,
            IntPtr dwInstance,
            uint dwParam1,
            uint dwParam2)
        {
            // Receive messages here
            Console.WriteLine("{0} {1} {2}",wMsg,dwParam1,dwParam2);


               if (wMsg == 963)
                {
                    dwParam1 = dwParam1 & 0xFFFF;
                    uint h_dw1 = 0;
                    uint l_dw1 = 0;
                    h_dw1 = dwParam1 & 0xFF;
                    l_dw1 = (dwParam1 >> 8) & 0xFF;




                    Console.WriteLine(Convert.ToString(wMsg, 16));
                    Console.WriteLine(Convert.ToString(h_dw1, 16));
                    Console.WriteLine(Convert.ToString(l_dw1, 16));
                    Console.WriteLine(Convert.ToString(dwParam2, 16));
                    Console.WriteLine("-------------------------------");
                }
                else
                {
                    Console.WriteLine(Convert.ToString(wMsg, 16));
                    Console.WriteLine(Convert.ToString(dwParam1, 16));
                    Console.WriteLine(Convert.ToString(dwParam2, 16));
                    Console.WriteLine("-------------------------------");
                }
        }


        public static void Main(String [] args)
        {
        	Console.WriteLine("Hello");
        	InputPort ip = new InputPort();
        	Console.WriteLine("devices-sum:{0}",InputPort.InputCount);
        	ip.Open(0);
        	ip.Start();
        	try
        	{
        		while(true)
	        	{
	        		Thread.Sleep(1);
	        	}
        	}
        	catch(Exception e)
        	{


        	}
        	finally
        	{
        		ip.Stop();
        		ip.Close();
        		Console.WriteLine("Bye~");
        	}
        	


        }
    }


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


        internal delegate void MidiInProc(
            IntPtr hMidiIn,
            uint wMsg,
            IntPtr dwInstance,
            uint dwParam1,
            uint 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);
    }
}

你可能感兴趣的:(WPF)