Java Sound. Eine Einführung  toc  prev  next


2.1. Das Midi Package

  • MIDI wire protocol, das ursprüngliche MIDI protocol, dient nur der Übertragung von "Steuerbefehlen" zwischen MIDI devices.
  • Ein standard MIDI file enthält MIDI events. Bestehend aus einer MIDI message, wie im MIDI wire protocol, aber mit zusätzlichen Informationen über das timing.

MIDI Messages

MidiMessage ist eine abstrakte Klasse die Ereignisse wie im MIDI wire protocol repräsentiert. Sie besitzen also keine timing-Informationen.

Drei MidiMessage subclasses:

  • ShortMessages
  • SysexMessages (Hersteller spezifische Informationen)
  • MetaMessages (z.B. Texte).

Midi device

Neben der SoundCard und externen Midi-Instrumenten ist jede Software, die das MidiDevice interface implementiert eine MidiDevice. Sie besitzt mindestens

  • Midi input und output port
  • eine innnere Klasse MidiDevice.Info
  • kann MidiMessages senden und empfangen

Sequencer

Ein sequencer kann sequences aufnehmen und wiedergeben. Dafür besitzt er:

  • transmitter zum Senden von Midi events
  • receiver zum Empfangen von Midi events
  • load Methode zum Laden von Midi files

Wenn er aufnimmt, fügt er den "nackten" Midi messages timing Informationen hinzu.
Bei der Wiedergabe durch z.B. einen Synthesizers entfernt er diese Informationen. Somit leistet den Übergang von MIDI wire protocol zu standard MIDI.

Synthesizers

Ein Synthesizer ist eine device zum erzeugen von Sound, somit die einzige in dem Package.

  • Empfängt über einen receiver.
  • Kontrolliert MIDI channel objects, meistens 16.
  • Durch bank- und program-number wird jedem Midi channel ein Instrument zugeordnet (preset der Soundcard oder soundbank Datei)

Die MidiDevice interface Hierachie:

 

2.2. Zugriff auf die Midi System Resourcen

MidiSystem

Eine Application kann von MidiSystem (muß nicht mit new erzeugt werden) folgende resources erhalten:

  • Sequencers
  • Synthesizers
  • Transmitters (Midi input ports)
  • Receivers (Midi output ports)
  • Data from standard MIDI files
  • Data from soundbank files

Diese methode liefern die default resources:

static Sequencer getSequencer()
static Synthesizer getSynthesizer()
static Receiver getReceiver()
static Transmitter getTransmitter()

Auch alle übrigen resources werden als array von MidiDevice.Info Objekten zurückgegeben:

static MidiDevice.Info[] getMidiDeviceInfo()

Jedes MidiDevice.Info Objekten enthält

  • Name
  • Version number
  • Vendor (Firmenname)
  • A description of the device

Durch Übergabe des MidiDevice.Info Objekts kann die entsprechende MidiDevice angefordert werden:

static MidiDevice getMidiDevice(MidiDevice.Info info)

Öffnen einer MidiDevice:

if (!(device.isOpen())) {
    try { 
        device.open();
    } catch (MidiUnavailableException e) {
        // Handle or throw exception...
    }
}

 

Senden einer Message an einen Receiver

ShortMessage myMsg = new ShortMessage();
// Start playing the note Middle C (60),
// moderately loud (velocity = 93).
myMsg.setMessage(ShortMessage.NOTE_ON, 0, 60, 93);
long timeStamp = -1;
// Get default Receiver.
Receiver rcvr = MidiSystem.getReceiver();
rcvr.send(myMsg, timeStamp);

Nachdem mit new eine neue ShortMessage erzeugt wurde. Er hält sie einen Inhalt.

void setMessage(int command, int channel, int data1, int data2)

Ein command könnte z.B. die Konstante ShortMessage.NOTE_ON sein.

void send(MidiMessage message, long timeStamp)

Die timeStamp -1 meint: Die Message soll so schnell wie möglich gesendet werden.

 

Verbinden von Transmitter und Receiver

Sequencer seq;
Transmitter seqTrans;
Synthesizer synth;
Receiver synthRcvr;
try {
    seq = MidiSystem.getSequencer();
    seqTrans = seq.getTransmitter();
    synth = MidiSystem.getSynthesizer();
    synthRcvr = synth.getReceiver();
    seqTrans.setReceiver(synthRcvr);
} catch (MidiUnavailableException e) {
    // handle or throw exception
}

Übrigens können so die decive und alle dazugehörigen transmitters und receivers geschlossen werden:

MidiDevice.close()

2.3. Abspielen, Aufzeichnen von Midi files

Sequence

  • Sequence (enthält Tracks)
  • Track (enthält MidiEvents)
  • MidiEvent

Ein MidiEvent kappselt eine MidiMessage, wie der Konstruktor zeigt

MidiEvent(MidiMessage message, long tick) 

Die time-stamp darf nicht wie bei der MidiMessage in Milisekunden angegeben werden, sondern in sogenannte ticks.

Die Länge eines ticks wird bestimmt in

  • Pulses (ticks) per quarter note (PPQ)
  • Ticks per frame (SMPTE time code)

mit Sequence.getDivisionType() erfährt man, welcher Type für die Sequence gilt.

Sequencer

Der default Sequencer wird geöffnet durch:

Sequencer sequencer;
// Get default sequencer.
sequencer = MidiSystem.getSequencer();
if (sequencer == null) {
    // Error -- sequencer device is not supported.
    // Inform user and return...
} else {
    // Acquire resources and make operational.
    sequencer.open(); 
}

Ein Midi file kann nur als Sequence in einen Sequencer geladen werden:

try {
    File myMidiFile = new File("seq1.mid");
    // Construct a Sequence object, and
    // load it into my sequencer.
    Sequence mySeq = MidiSystem.getSequence(myMidiFile);
    sequencer.setSequence(mySeq);
} catch (Exception e) {
    // Handle error
}

Abspielen eines Midi files

geschieht dann durch

void start()
void stop()

des Sequencers.

Recording und Saving einer Sequence

  1. Mit MidiSystem.getSequencer einen neuen Sequencer anlegen.
  2. “Wiring” der Midi connections:



  3. Neue Sequence erzeugen mit

    mySeq = new Sequence(Sequence.PPQ, 10);

    Argumente sind divisionType and a timing resolution.
  4. Sequencer.setSequence
  5. Sequencer.recordEnable
  6. Sequencer.startRecording
  7. Sequencer.stopRecording
  8. Midi Datei speichern mit MidiSystem.write

Java Sound. Eine Einführung  toc  prev  next                         [ back to  a P a g e ]