package org.herac.tuxguitar.io.midi;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import org.herac.tuxguitar.io.midi.base.MidiEvent;
import org.herac.tuxguitar.io.midi.base.MidiMessage;
import org.herac.tuxguitar.io.midi.base.MidiSequence;
import org.herac.tuxguitar.io.midi.base.MidiTrack;
public class MidiFileWriter implements MidiFileHeader {
private static int writeEvent(MidiEvent event, MidiEvent previous,
OutputStream out) throws IOException {
int length = writeVariableLengthQuantity(((previous != null) ? (event
.getTick() - previous.getTick()) : 0), out);
MidiMessage message = event.getMessage();
if (message.getType() == MidiMessage.TYPE_SHORT) {
length += writeShortMessage(message, out);
} else if (message.getType() == MidiMessage.TYPE_META) {
length += writeMetaMessage(message, out);
}
return length;
}
private static int writeMetaMessage(MidiMessage message, OutputStream out)
throws IOException {
int length = 0;
byte[] data = message.getData();
if (out != null) {
out.write(0xFF);
out.write(message.getCommand());
}
length += 2;
length += writeVariableLengthQuantity(data.length, out);
if (out != null) {
out.write(data);
}
length += data.length;
return length;
}
private static int writeShortMessage(MidiMessage message, OutputStream out)
throws IOException {
byte[] data = message.getData();
int length = data.length;
if (out != null) {
out.write(message.getData(), 0, length);
}
return length;
}
private static int writeTrack(MidiTrack track, DataOutputStream out)
throws IOException {
int length = 0;
if (out != null) {
out.writeInt(TRACK_MAGIC);
}
if (out != null) {
out.writeInt(writeTrack(track, null));
}
MidiEvent previous = null;
for (int i = 0; i < track.size(); i++) {
MidiEvent event = track.get(i);
length += writeEvent(event, previous, out);
previous = event;
}
return length;
}
private static int writeVariableLengthQuantity(long value, OutputStream out)
throws IOException {
boolean started = false;
int length = 0;
int data = (int) ((value >> 21) & 0x7f);
if (data != 0) {
if (out != null) {
out.write(data | 0x80);
}
length++;
started = true;
}
data = (int) ((value >> 14) & 0x7f);
if (data != 0 || started) {
if (out != null) {
out.write(data | 0x80);
}
length++;
started = true;
}
data = (int) ((value >> 7) & 0x7f);
if (data != 0 || started) {
if (out != null) {
out.write(data | 0x80);
}
length++;
}
data = (int) (value & 0x7f);
if (out != null) {
out.write(data);
}
length++;
return length;
}
public void write(MidiSequence sequence, int type, OutputStream stream)
throws IOException {
DataOutputStream out = new DataOutputStream(stream);
out.writeInt(HEADER_MAGIC);
out.writeInt(HEADER_LENGTH);
out.writeShort(type);
out.writeShort(sequence.countTracks());
out.writeShort((sequence.getDivisionType() == MidiSequence.PPQ) ? (sequence
.getResolution() & 0x7fff) : 0);
for (int i = 0; i < sequence.countTracks(); i++) {
writeTrack(sequence.getTrack(i), out);
}
out.flush();
out.close();
}
}