Java Sound Midi

Jepp ich habe die Stelle gefunden wo openMidi aufgerufen wurde -
ich glaube ich muss im Programm anders vorgehen

kann man eine Comobox neu aufbauen wenn man sie angeklickt hat ?
also mit
Java:
  jComboMidi.removeAllItems();
  jComboMidi.addItem("none");

arbeiten wenn man da drin ist :
private void jComboMidiActionPerformed(java.awt.event.ActionEvent evt) { }
?

im Moment habe ich ein Button der dafür sorgt das die Liste der MidiPorts neu eingelesen wird - währe natürlich eleganter wenn ich das in einem Aufwasch machen könnte

Nachtrag:
ich glaube ich habe ein BUG in swing Combobox gefunden - COOL :-)
ich habe zwei identische Einträge in Position 2 und 3 - aber ich bekomme es nicht hin das er sagt es wurde Eintrag 3 angesprochen - er sagt immer 2
scheinbar wird bei jComboMidi.getSelectedIndex(); über den String im Eintrag gearbeitet und wenn zwei identische gibt gibt er immer die erste Position an
 
Zuletzt bearbeitet:
Natürlich geht das.

zum Nachtrag: man kann sich darüber streiten, ob das ein Bug ist. Meiner Meinung nach ist es keiner, weil man sowieso keine 2 identischen Elemente in eine Combobox hinzufügt ;)
 
Tja mittlerweile bin ich soweit das mein Programm erkennt das eine Taste am Keyboard gedrückt wurde.
Leider kommen nur blödsinnsdaten an

die frage ist - warum :-(

im Moment habe ich keine Idee dazu

auch wenn ich das erzeugte MIDI File speichere und mir dann per hexdump den inhalt ansehe sieht das nicht so aus wie ein Midi File aussehen soll

Nachtrag:
Nu verstehe ich nix mehr
ich füge in einem zweiten Track daten direkt über shortmessage ein und auch da sieht mein MIDI File nicht so aus wie es sein sollte :-(
 
Zuletzt bearbeitet:
Drei fragen,

wie sieht dein file aus? und wie sollte es aussehen?

Und wie sieht der Code aus mit dem du deine Message erzeugst?

Es kann keiner helfen wenn er das Problem nicht sehen kann ;)
 
also ich habe eine eigene Classe für Midi erzeut und hier mal der gesamte code:

Java:
public class MidiPort {
    
    private MidiDevice.Info[] infos;
    private MidiDevice midiIO;
    private Receiver     midiRcvr, seqRcvr;
    private Transmitter  midiTrans;
    private Sequencer    seqdev;
    private int messinx;
    Sequence mySeq;
    Track seqspur;

    boolean[] runLevel = { false, false, false, false, false, false };
    // 0 Port Offen, 1 Sequnzer init, 2 Sequenz vorhanden, 3 Track vorhanden, 4 Record möglich, 5 aufzeichnen

    String[] getMidiPorts() {
        String[] sdev;
        //MIDI:
        infos = MidiSystem.getMidiDeviceInfo();
        sdev = new String[infos.length];
        for (int loo = 0; loo < infos.length; loo++) {
            sdev[loo] = infos[loo].getName();
        }
        return sdev;
    }

   void openMidi(int devindex) {
     if (devindex >= 0)  {
       // midiStatus = infos[devindex].getName();
       // Midi Device öffnen
       try {
           midiIO = MidiSystem.getMidiDevice( infos[devindex] );
           midiIO.open();
           midiTrans = midiIO.getTransmitter();
           runLevel[0]= true;
           // midi port ok
       } catch (MidiUnavailableException e1) {
           //midiStatus = midiStatus + "Device Fehler /n" ;
           //System.out.println("MIDI Geräte - Fehler!");
           //e1.printStackTrace();
       }
       // sequencer einrichten
       try {
          seqdev = MidiSystem.getSequencer();
          seqdev.open();
          seqdev.setTempoInBPM(90);
          seqRcvr = seqdev.getReceiver();

          midiTrans.setReceiver(seqRcvr);
          runLevel[1] = true;
          // sequenzer ok
        }
        catch (MidiUnavailableException e1)  {
           // midiStatus = midiStatus + ("Sequenzer Error /n");
        }
       // sequence mit einem Track erzeugen
       try {
          mySeq = new Sequence(Sequence.PPQ, 8);
          seqspur = mySeq.createTrack();
          runLevel[2] = true;
          runLevel[3] = true;
          // sequenz und Track ok
        } catch (Exception e1) {
          //midiStatus = midiStatus + "Fehler beim anlegen von Squenz oder Track /n";
        }
       try {
           seqdev.setSequence(mySeq);
           // runLevel = runLevel | 8;
           // squenzer hat sequenze
       } catch (Exception e1)  {
           //midiStatus = midiStatus + ("kein Sequenze für Sequenzer /n");
        }
       // aufzeichen möglich machen
       seqdev.recordEnable(seqspur, -1);
       runLevel[4] = true;
       } else {   // none angewählt
         if (runLevel[0]) {
             midiTrans.close();
             runLevel[0] = false;
         }
       } // end if
   }

   void recOnOff() {
       if ( runLevel[4] ) {
         if ( seqdev.isRecording() ) {
            seqdev.stopRecording();
//seqdev.recordDisable(track);
            runLevel[5] = false;
            makeTestTrack();
            File midfile = new File("my.mid");
            try {
              MidiSystem.write(mySeq, 2, midfile);
            }
            catch (IOException e ) {
            }
         } else {
            seqdev.startRecording();
            runLevel[5] = true;
            messinx = 1;
         }
       }
   }

   String midiAsString() {
        String zeile = "\n";
        MidiEvent mereignis;
        MidiMessage mmess;
        byte[] datafeld;
        int zwert;
     if (messinx < seqspur.size()) {
       zeile = zeile + Integer.toString(messinx)  + ":";
       mereignis = seqspur.get(messinx);
       mmess = mereignis.getMessage();
       datafeld = mmess.getMessage();
       for (int loo = 0; loo < mmess.getLength(); loo++) {
           zwert = (int) (datafeld[loo] & 0xff);
           zeile = zeile + Integer.toHexString( zwert ) + " ";
           // zeile = zeile + Byte.toString(datafeld[loo]) + " ";
       }
       zeile = zeile + Long.toString(mereignis.getTick());
       messinx++;
     }
       return zeile;
   }

   boolean midiDatacomein() {
       return (messinx < seqspur.size());
   }

   String getStatusAsTxt() {
      String gszeile ;
      gszeile = "MIDI Port Open " + Boolean.toString(runLevel[0]) + "\n";
      gszeile = gszeile + "Sequenzer ON " + Boolean.toString(runLevel[1]) + "\n";
      gszeile = gszeile + "Sequenze verfügbar " + Boolean.toString(runLevel[2]) + "\n";
      gszeile = gszeile + "Track vorhandem  " + Boolean.toString(runLevel[3]) + "\n";
      gszeile = gszeile + "Record Enable  " + Boolean.toString(runLevel[4]) + "\n";
      gszeile = gszeile + "Recording " + Boolean.toString(runLevel[5]);
      return gszeile;
   }

   void makeTestTrack() {
       long tpos = 8;
       seqspur = mySeq.createTrack();
       ShortMessage msg ;
       for (int tonleiter = 60; tonleiter < 70; tonleiter++) {
           try {
           msg = new ShortMessage();
           msg.setMessage(ShortMessage.NOTE_ON, 0, tonleiter , 64);
           seqspur.add(new MidiEvent(msg, tpos));
           tpos = tpos + 8;
           msg = new ShortMessage();
           msg.setMessage(ShortMessage.NOTE_ON, 0, tonleiter, 0);
           seqspur.add(new MidiEvent(msg, tpos));
           tpos = tpos + 8;
           } catch (Exception e) {

           }
       }
   }
}

und in hier passiert der wichtige aufruf
ich starte die aufzeichnung über ein Event

Java:
private void jRadioRecordActionPerformed(java.awt.event.ActionEvent evt) {                                             
        // TODO add your handling code here: Record on / off
        exmidi.recOnOff();
        if (exmidi.runLevel[5]) {
            // zeit.start();
        } else {
            zeit.stop();
        }
        jRadioRecord.setSelected( exmidi.runLevel[5] );
    }

und dort erzeuge ich eine mididatei - ein track durch tastendruck und ein track zu kontrolle

und in dem midifile solle dann die MIDI daten autauchen wie z.b 0x90 0x3C 0x64
erste zahl bedeutet ton (90) an zweite bedeutet ton höhe (C) 3. zahl bedeutet die stärke

beschreibung aufbau MIDI Datei
http://www.larsrichter-online.de/lmids/midformat.htm

und hier der hexdump der datei

00000000 4d 54 68 64 00 00 00 06 00 01 00 02 00 08 4d 54 |MThd..........MT|
00000010 72 6b 00 00 00 2f 48 90 3c 73 02 3c 00 04 3e 66 |rk.../H.<s.<..>f|
00000020 02 3e 00 04 40 76 02 40 00 03 41 7b 02 41 00 04 |.>..@v.@..A{.A..|
00000030 43 7c 02 43 00 03 45 7b 02 45 00 04 47 7d 02 47 |C|.C..E{.E..G}.G|
00000040 00 00 ff 2f 00 4d 54 72 6b 00 00 00 41 08 90 3c |.../.MTrk...A..<|
00000050 40 08 3c 00 08 3d 40 08 3d 00 08 3e 40 08 3e 00 |@.<..=@.=..>@.>.|
00000060 08 3f 40 08 3f 00 08 40 40 08 40 00 08 41 40 08 |.?@.?..@@.@..A@.|
00000070 41 00 08 42 40 08 42 00 08 43 40 08 43 00 08 44 |A..B@.B..C@.C..D|
00000080 40 08 44 00 08 45 40 08 45 00 00 ff 2f 00 |@.D..E@.E.../.|


ab adresse 17 ist der erste Ton vorhanden und ab adresse x4E sollte der 2. track losgehen

soweit der wichtige teil

zum verständnis ich habe auf der Swing oberfläche eine Combo box die mir die verfügbaren MIDI Geräte anzeigt und ein Button um diese Liste neu auzubauen , dann gibt es noch ein Texfeld zur anzeige von ergebnissen (Jtextausgabe) und ein radiobutton zum starten der aufzeichnung und beenden.
dann gibts noch ein timer in dem ich einfach nachkucke ob was eingegangen ist

Java:
// eingefügt by susanne
    MidiPort exmidi = new MidiPort();
    javax.swing.Timer zeit = new javax.swing.Timer(83, new ClockListener());
    // 83 ms = takt 90 8 tiks per takt
    class ClockListener implements ActionListener {
    	public void actionPerformed(ActionEvent e) {
           // zeit abgelaufen
            if (exmidi.midiDatacomein() ) {
                jTextAusgabe.append( exmidi.midiAsString());
            }
        }
    }
    // ende

    private void jComboMidiActionPerformed(java.awt.event.ActionEvent evt) {                                           
        // TODO add your handling code here: Midi Devices anzeigen
        int pinx = jComboMidi.getSelectedIndex();
       // achtung bei der übergabe minus eins da erster eintrag none
        if (pinx > 0 ) {
            exmidi.openMidi(pinx - 1);
        }
        jTextAusgabe.setText("Zeile " + Integer.toString(pinx)) ;

        jTextAusgabe.append( exmidi.getStatusAsTxt());
    }                                          

    private void jButtonMidiPortActionPerformed(java.awt.event.ActionEvent evt) {                                                
        // TODO add your handling code here: update Midi Devicelist in jComboMidi
        String[] devl;
        jComboMidi.removeAllItems();
        jComboMidi.addItem("none");

        devl = exmidi.getMidiPorts();
        for (int loo=0 ; loo < devl.length; loo++  ) {
            jComboMidi.addItem(devl[loo]);
        }
    }

damit sind alle codeteile online :-)
 
Zuletzt bearbeitet:
ich bin schon mal ein schritt weiter :-)

ich habe durch ein Debug programm festgestellt das mein Keyboard auch andre MIDI Ereignisse sendet wie Ton an/aus

also habe ich den Timer wider eingeschaltet und

aus dem
if (exmidi.midiDatacomein() )
ist ein
while (exmidi.midiDatacomein() )
geworden

und siehe da ich sehe Noten

und nu suche ich ne andre beschreibung zu der MIDI Datei aufbau - ev gibts da ja mehrere Versionen ....
und ich mach mir unnötig sorgen :-)

edit:
hmm ich sehe nicht alle tasten - ich vermute mal da gibts im hintergrund ein puffer der mir vollläuft
auch daran zu erkennen das ich ein bestimmtes eingabetempo brauche damit überhaupt noten angezeigt werden ...

noch ein step weiter
was die sache stört sind die MidiSync Daten die von Keyboard kommen - also mehr in Midi einarbeiten und klären wie ich die Syncdaten rausfilter - ausschalten kann ich die sync geschichte scheinbar nicht
 
Zuletzt bearbeitet:
Was ich ermittelt habe ist :
was mein Programm stört ist das "Active Sensing"
man kanns leider nicht ausschalten
das Keybord sendet einfach daten um mitzuteilen ich bin noch da
da man es nicht ausschalten kann und auch nicht filtern im programm hat sich das projekt anschluss vom Keyboard an Java erledigt :-(
 
Zuletzt bearbeitet:
ich habe den Fehler gefunden - ich habe es hinbekommen

letzlich anfängerfehler - ich habe immer das squenzende ausgelesen :-(
und das er ab und zu noten gezeigt hatte lag daran das er auch den vorletzen eintrag ausgelesen hatte wenn ich schnell genug war mit Tippen...
 
Zuletzt bearbeitet:
Zurück