2010-01-02 13 views
7

Compré un teclado MIDI para mi cumpleaños. Encontré un programa (MidiPiano) que recibe señales de la entrada MIDI y las traduce en música, pero me gustaría escribir una.Obtener señales de un puerto MIDI en C#

¿Dónde puedo encontrar documentación para hacer tal tarea? El protocolo MIDI está bien documentado, pero no los puertos MIDI.

Revisé dos proyectos de CodeProject (Proyecto MIDI y C# MIDI Toolkit), pero pasé muchas horas sin acercarme a mi objetivo.

Una referencia a un proyecto estará bien, pero por favor, solo C#.

Respuesta

2

No pude encontrar mucho tampoco, pero como dice Josh, Carl definitivamente ha trabajado bastante en MIDI, así que tal vez le dé un correo electrónico ... incluso puede responder, pero normalmente es un VB. Net Guy a menos que alguien haya portado sus cosas a C#?

Para algunas otras referencias que parecían prometedores ...

Si usted está buscando una solución pura C# ... echar un vistazo a Alvas.Audio. Se ve un poco alto para lo que estás preguntando, pero puede ser de alguna ayuda.

También puede que project midi

+0

Gracias Marcar, y por favor vea mi comentario a Josh. Le preguntaré a Carl después de converger su proyecto a WPF. Claro que tendré muchas preguntas entonces. – gideonrv

6

Es necesario para envolver todas las funciones necesarias que figuran en http://msdn.microsoft.com/en-us/library/dd757277(VS.85).aspx

no es demasiado difícil si sólo está utilizando mensajes cortos, las cosas se ponen un poco más complicado si usted quiere hacer SysEx o transmisión de salida.

Todo lo que necesita para una entrada básica El puerto es para obtener las ID de entrada válidas (InputCount -1), pasar una ID válida para abrir, iniciar la entrada, recibir los mensajes a través de un delegado ... Detener la entrada y luego finalmente ciérralo. Este es un ejemplo muy aproximado de cómo se podría lograr esto: tendrá que hacer algunas comprobaciones y tener cuidado de que el puerto no se recoja antes de que se cierre y de que se haya producido la devolución de llamada cerrada o de que se congele el sistema.

¡Buena suerte!

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

Davey dice: "Recibe los mensajes a través de un delegado ...", y ese es exactamente mi problema actual. ¿NativeMethods.MidiInProc resuelve el problema? Tan simple, ¿un delegado listo? Gracias, Davey, lo veré el próximo fin de semana. – gideonrv

1

Uso de C# Midi Kit de herramientas para recibir la información MIDI del teclado (conectado a la entrada MIDI IN-puerto de que la tarjeta de sonido). Para crear audio (música o tonos), necesita generar una transmisión continua de datos de audio digital. Puede comenzar con C# Synth Toolkit (el mismo autor que el kit de herramientas midi) para escribir su propio sintetizador.

Pero también puede descargar un programa secuenciador gratuito (código abierto) (audacity, por ejemplo) y usar complementos de instrumentos VST para hacer el trabajo por usted. Hay muchos complementos gratuitos disponibles en la web.

2

Estoy en proceso de desarrollo del sistema de comunicación C# midi. El kit de herramientas midi de Sanford es bueno, pero la implementación de Leslie tiene muchas mejoras que hacen que el código sea menos legible. Mi código es lo más simple posible. Si quieres, puedes unirte a mí. En unos días publico un monitor midi totalmente operativo. Basta con mirar http://puremidi.codeplex.com/

+0

Gracias por su respuesta. Ahora estoy involucrado en otros proyectos de WPF/ADO.Net/Interop, y, por ahora, pasará un tiempo antes de que pueda volver a la música. Cuando llegue el momento, estaré en contacto. – gideonrv

0

He resuelto esto de una manera indirecta escribiendo una secuencia de comandos de Python para transmitir un paquete UDP cada vez que se activa o desactiva una nota en el teclado MIDI.

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

De esa manera las cosas MIDI específico de la plataforma se envuelve, y yo puedo escribir independiente de la plataforma de código C# para recoger el paquete UDP.