2011-08-04 45 views
8

He diseñado mi propio sintetizador en java y ahora quiero conectarlo con un teclado midi. Mi clase a continuación busca en todos los dispositivos midi que tienen transmisores. Encuentra con éxito mi teclado midi. Agrego mis propios receptores a cada transmisor para cada dispositivo para que recoja todo lo posible. Después de leer todos los documentos de ayuda y el documento de Java, sé que un transmisor envía MidiEvents a un receptor que luego los maneja con el método de envío. Así que escribí mi propia clase interna implementando Receiver y simplemente usé una instrucción println para verificar si había algo detectado en el método de envío. Sin embargo, nada es recogido en absoluto. Parece que hay muy poca ayuda para hacer algo tan simple y he revisado cada archivo de ayuda, javadoc y foro. Estoy seguro de que debe ser algo realmente obvio que de alguna manera me he perdido.Java recibiendo entrada del teclado MIDI

Mi sintetizador no se debe confundir con la interfaz Sintetizador y no es un instrumento midi. Utiliza un algoritmo de síntesis y tiene un método de reproducción. Básicamente, solo necesito que el teclado midi envíe una nota sobre el evento que invocará el método de reproducción.

import javax.sound.midi.*; 
import java.util.ArrayList; 
import java.util.List; 
import java.io.*; 
public class MidiHandler 
{ 
    //ArrayList of MidiDevices 
    private ArrayList<MidiDevice> devices = new ArrayList<MidiDevice>(); 

    public MidiHandler() 
    { 
     MidiDevice device; 
     MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo(); 
     for (int i = 0; i < infos.length; i++) { 
      try { 
       device = MidiSystem.getMidiDevice(infos[i]); 
       //does the device have any transmitters? 
       if (device.getTransmitters().size() > 0) { 
        //if it does, add it to the device list 
        System.out.println(infos[i] + ": " + device.getTransmitters().size()); 
        devices.add(device); 
       } 
      } catch (MidiUnavailableException e) {} 
     } 
     //if any transmitting devices were found 
     if(devices.size()>0) { 
      //for each device 
      for(int i = 0; i<devices.size(); i++) { 
       try { 
        //get all transmitters 
        List<Transmitter> transmitters = devices.get(i).getTransmitters(); 
        //and for each transmitter 
        for(int j = 0; j<transmitters.size();j++) { 
         //create a new receiver 
         transmitters.get(i).setReceiver(
          //using my own MidiInputReceiver 
          new MidiInputReceiver(devices.get(i).getDeviceInfo().toString()) 
         ); 
        } 
        //open each device 
        devices.get(i).open(); 
        //if code gets this far without throwing an exception 
        //print a success message 
        System.out.println(devices.get(i).getDeviceInfo()+" Was Opened"); 
       } catch (MidiUnavailableException e) {} 
      } 
     } 
    } 
    //tried to write my own class. I thought the send method handles an MidiEvents sent to it 
    public class MidiInputReceiver implements Receiver { 
     public String name; 
     public MidiInputReceiver(String name) { 
      this.name = name; 
     } 
     public void send(MidiMessage msg, long timeStamp) { 
      System.out.println("midi received"); 
     } 
     public void close() {} 
    } 
} 

NOTA: ya he visto esto: Java MIDI - getting data from piano?.

y esto: http://www.jsresources.org/examples/MidiInDump.html

interfaz secuenciador veía manera de complicado para lo que yo quiero también.

Respuesta

12

que he encontrado que la MidiDevice getTransmitters() aparece para devolver la lista de actualmente ya abiertos transmisores, no transmisores que están disponibles que se abra. Creo que la forma de abrir un nuevo transmisor es a través del método getTransmitter(). He modificado el código para hacer esto:

import javax.sound.midi.*; 
import java.util.ArrayList; 
import java.util.List; 
import java.io.*; 
    public class MidiHandler 
{ 

    public MidiHandler() 
    { 
     MidiDevice device; 
     MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo(); 
     for (int i = 0; i < infos.length; i++) { 
      try { 
      device = MidiSystem.getMidiDevice(infos[i]); 
      //does the device have any transmitters? 
      //if it does, add it to the device list 
      System.out.println(infos[i]); 

      //get all transmitters 
      List<Transmitter> transmitters = device.getTransmitters(); 
      //and for each transmitter 

      for(int j = 0; j<transmitters.size();j++) { 
       //create a new receiver 
       transmitters.get(j).setReceiver(
         //using my own MidiInputReceiver 
         new MidiInputReceiver(device.getDeviceInfo().toString()) 
       ); 
      } 

      Transmitter trans = device.getTransmitter(); 
      trans.setReceiver(new MidiInputReceiver(device.getDeviceInfo().toString())); 

      //open each device 
      device.open(); 
      //if code gets this far without throwing an exception 
      //print a success message 
      System.out.println(device.getDeviceInfo()+" Was Opened"); 


     } catch (MidiUnavailableException e) {} 
    } 


} 
//tried to write my own class. I thought the send method handles an MidiEvents sent to it 
public class MidiInputReceiver implements Receiver { 
    public String name; 
    public MidiInputReceiver(String name) { 
     this.name = name; 
    } 
    public void send(MidiMessage msg, long timeStamp) { 
     System.out.println("midi received"); 
    } 
    public void close() {} 
    } 
} 

en mi hardware (Tengo un simple controlador MIDI USB enchufado), el código imprime correctamente "MIDI recibidos" después de crear una instancia de MidiHandler.

Espero que esto ayude!

+0

Excelente muchas gracias! Esto funciona y es un código menos intrincado también. – Jonathan

2

Descubrí que debe abrir el dispositivo antes de llamar a setRecceiver(); de lo contrario, se llama al método send() del receptor con cualquier dato MIDI basura de la última vez que ejecutó la aplicación.

device.open(); 

Transmitter trans = device.getTransmitter();  
// set new receiver after opening so that the input buffer will be flushed 
trans.setReceiver(new MidiInputReceiver(device.getDeviceInfo().toString())); 
+0

es importante abrir el dispositivo antes de agregar receptores – codewandler

Cuestiones relacionadas