package com.xenoage.zong.desktop.io.midi.out; import javax.sound.midi.InvalidMidiDataException; import javax.sound.midi.MetaMessage; import javax.sound.midi.MidiEvent; import javax.sound.midi.Sequence; import javax.sound.midi.ShortMessage; import javax.sound.midi.Track; import com.sun.media.sound.MidiUtils; import com.sun.media.sound.MidiUtils.TempoCache; import com.xenoage.zong.io.midi.out.MidiSequenceWriter; /** * Java SE implementation of a {@link MidiSequenceWriter}. * * @author Andreas Wenger */ public class JseMidiSequenceWriter extends MidiSequenceWriter<Sequence> { private Sequence sequence = null; private Track[] tracks; private TempoCache tempoCache = null; @Override public void init(int tracksCount, int resolutionPpq) { //create sequence try { sequence = new Sequence(Sequence.PPQ, resolutionPpq); } catch (InvalidMidiDataException e) { throw new RuntimeException(); //TODO } //add tracks tracks = new Track[tracksCount]; for (int i = 0; i < tracksCount; i++) { tracks[i] = sequence.createTrack(); } } @Override public void writeShortMessage(int track, int channel, long tick, int command, int data1, int data2) { try { ShortMessage message = new ShortMessage(); message.setMessage(command, channel, data1, data2); tracks[track].add(new MidiEvent(message, tick)); } catch (InvalidMidiDataException ex) { //ignore - TODO } } @Override public void writeMetaMessage(int track, long tick, int type, byte... data) { try { MetaMessage message = new MetaMessage(); message.setMessage(type, data, data.length); tracks[track].add(new MidiEvent(message, tick)); } catch (InvalidMidiDataException ex) { //ignore - TODO } //when it is a tempo change, the tempo cache is obsolete if (type == typeTempo) tempoCache = null; } @Override public long getLength() { return sequence.getTickLength(); } @Override public long tickToMicrosecond(long tick) { //recompute tempo cache if required if (tempoCache == null) tempoCache = new TempoCache(sequence); //compute position return MidiUtils.tick2microsecond(sequence, tick, tempoCache); } @Override protected Sequence getSequence() { return sequence; } }