UHU-StartseiteInformatikTechnikenjavamidi
MidiBase



package midi;

import java.util.ArrayList;
import java.util.List;
import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Receiver;
import javax.sound.midi.ShortMessage;
import javax.sound.midi.SysexMessage;

/**
 *
 * @author Robert Rothhardt
 * @version 0.019
 * @serial 1970
 */
public class MidiBase{
  
  public static final String PROGRAM_CHANGE = "pc";
  public static final String CONTROL_CHANGE = "cc";
  public static final String NOTE_ON        = "no";
  public static final String NOTE_OFF       = "nf";
  public static final String BANK_SELECT    = "bs";
  
  private static String infoToString(MidiDevice.Info it){
    return it.getName()+":"+it.getDescription()+" ("+it.getVersion()+")/"+it.hashCode();
  }
  
/*  private static String bytesToString(byte[] ba){
    String result = "[";
    for (int i=0; i<ba.length; i++){
      String tmp = Integer.toHexString(ba[i]);
      if (tmp.length()==1) tmp = "0"+tmp;
      result += tmp.substring(tmp.length()-2) +",";
    }
    result = result.substring(0,result.length()-1)+"]";
    return result;
  }
*/  
  private static byte[] toBytes(List<Integer> bytes){
    byte[] result = new byte[bytes.size()];
    for (int i=0; i<bytes.size(); i++){
      result[i] = bytes.get(i).byteValue();
    }
    return result;
  }

  /**
   * Wandelt eine Shortmessage in eine Zeichenkette um
   * @param sm ShortMessage
   * @return Zeichenkette, die die Repräsentation der ShortMessage enthält
   */
  public static String dump(ShortMessage sm){
    String result = "";
    result += sm.getCommand()+"#";
    result += sm.getChannel()+",";
    result += sm.getData1();
    if (sm.getLength()>2){        
      result +=",";
      result += sm.getData2();
    }  
    return result;
  }
  
  /**
   * Wandelt ein HexNibble in die entsprechende Zahl um
   * @param c Character 0..9,A..F
   * @return die korrespondierende Zahl zwischen 0..15
   */
  public static byte fromHex(char c){
    if (c<58) return (byte) (c-48); else return (byte) (c-55);
  }
  
  /**
   * Übersetzt eine Zeichenkette in eine ShortMessage
   * @param content beispielsweise "pc#0:71"
   * @return die zugehörige ShortMessage
   * @throws InvalidMidiDataException 
   */
  public static ShortMessage translate(String content) throws InvalidMidiDataException{
    ShortMessage result = new ShortMessage();
    int chp = content.indexOf("#");
    int channel = 0;
    if (chp>=0) channel = fromHex(content.charAt(chp+1));
    int base = 0;
    switch (content.substring(0,2)){
      case PROGRAM_CHANGE: base = 0xC0; break;
      case CONTROL_CHANGE: base = 0xB0; break;
      case NOTE_ON       : base = 0x90; break;
      case NOTE_OFF      : base = 0x80; break;
    }
    String[] parA = content.split(":");
    byte d1 = Byte.parseByte(parA[1]);
    if (parA.length==2) result.setMessage(base, channel, d1, 0);
    else result.setMessage(base, channel, d1, Byte.parseByte(parA[2]));
    return result;
  }
  
  /**
   * Das aktuell eingestellte MidiDevice, wenn init() aufgerufen wurde, sonst null
   */
  public static MidiDevice midiDevice = null;
  // public static Synthesizer synth;
  
  /**
   * Stellt ein neues MidiDevice ein
   * @param md MidiDevice, wie in der Midi-schnittstelle @see javax.sound.midi definiert.
   * @throws MidiUnavailableException 
   */
  public static void setDevice(MidiDevice md) throws MidiUnavailableException{
    midiDevice.close();
    midiDevice = md;
    midiDevice.open();
  }
  
  /**
   * Übersetzt das Device direkt aus dem infoString und setzt dieses Device
   * @param infoString Zeiechenkette, wie sie als Eintrag von allDevices() zurückkommt
   * @throws MidiUnavailableException 
   */
  public static void setDevice(String infoString) throws MidiUnavailableException{
    MidiDevice.Info[] allDevices = MidiSystem.getMidiDeviceInfo();
    for (int i=0; i<allDevices.length; i++){
      if (infoToString(allDevices[i]).equals(infoString)){
        setDevice(MidiSystem.getMidiDevice(allDevices[i]));
      }          
    }
  }

  /**
   * Setzt ein erstes Device, um den Zugang zur Midischnittstelle zu ermöglichen
   * @throws MidiUnavailableException 
   */
  public static void init() throws MidiUnavailableException{
    // hier ein anderes Device holen: MidiDevice device = MidiSystem.getDevice(info);
    midiDevice = MidiSystem.getSynthesizer();
/*
    synth = MidiSystem.getSynthesizer(); 
    synth.open(); **/
  }
  
  /**
   * Sendet eine ShortMessage. @see translate
   * @param sequence
   * @throws MidiUnavailableException
   * @throws InvalidMidiDataException
   * @throws InterruptedException 
   */
  public static void send(String sequence) throws MidiUnavailableException, InvalidMidiDataException, InterruptedException{
    if (!midiDevice.isOpen()) midiDevice.open();
    Receiver rcvr = midiDevice.getReceiver();
    rcvr.send(translate(sequence), -1);
  }
  
  public static void send(SysexMessage sx) throws MidiUnavailableException, InvalidMidiDataException, InterruptedException{
    if (!midiDevice.isOpen()) midiDevice.open();
    Receiver rcvr = midiDevice.getReceiver();
    rcvr.send(sx, -1);
  }
  
  /**
   * Sendet eine Serie von Bytes an das aktuelle Device. Die Bytes dürfen jeden Wert zwischen
   * 0..127 haben; eine Unterscheidung zwischen Status- und Datenbyte wird nicht vorgenommen.
   * @param sequence
   * @throws MidiUnavailableException
   * @throws InvalidMidiDataException
   * @throws InterruptedException
   */
  public static void send(List<Integer> sequence) throws MidiUnavailableException, InvalidMidiDataException, InterruptedException{
    if (!midiDevice.isOpen()) midiDevice.open();
    Receiver rcvr = midiDevice.getReceiver();
    AnyMidiMessage am = new AnyMidiMessage(toBytes(sequence));
    System.out.println(am); 
    rcvr.send(am , -1); 
/*    SysexMessage sx = new SysexMessage();
    byte[] ba = toBytes(sequence);
    sx.setMessage(ba, ba.length);
    rcvr.send(sx,-1); */
  }
  
  /**
   * Gibt eine Liste aller vorhandenen Devices zurück
   * @return 
   */
  public static List<String> allDevices(){
    List<String> result = new ArrayList<>();
    MidiDevice.Info[] allDevices = MidiSystem.getMidiDeviceInfo();
    for (int i=0; i<allDevices.length; i++){
      result.add(infoToString(allDevices[i]));
    }
    return result;
  }
  
  /**
   * Gibt den InfoString für das aktuelle Device zurück
   * @return Zeichenkette des aktuellen Devices
   */
  public static String getCurrentDeviceAsString(){
    return infoToString(midiDevice.getDeviceInfo());
  }
  
  public static void main(String[] args) throws MidiUnavailableException, InvalidMidiDataException, InterruptedException{
    MidiDevice.Info[] allDevices = MidiSystem.getMidiDeviceInfo();
    for (int i=0; i<allDevices.length; i++) System.out.println(infoToString(allDevices[i]));
    init();
    setDevice("1:Roland SonicCell:External MIDI Port (5.10)");
    send("pc#0:71");
    Thread.sleep(200);
    send("no#0:64:64");
    Thread.sleep(1000);
    send("nf#0:64:64");
    SonicCell sc = new SonicCell();
    send(sc.changeProgram(0,121,0,1));
  }
}


optimal sichtbar mit Firefox Formeln mit asciimath Druckversion