package org.herac.tuxguitar.io.gervill;
import java.io.OutputStream;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.sound.midi.MetaMessage;
import javax.sound.midi.MidiEvent;
import javax.sound.midi.MidiMessage;
import javax.sound.midi.Receiver;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import org.herac.tuxguitar.song.models.TGDuration;
public class MidiToAudioWriter {
private static void sort(List<MidiEvent> events) {
Collections.sort(events, new Comparator<MidiEvent>() {
public int compare(MidiEvent e1, MidiEvent e2) {
return (int) (e1.getTick() - e2.getTick());
}
});
}
public static void write(OutputStream out, List<MidiEvent> events,
MidiToAudioSettings settings) throws Throwable {
MidiToAudioSynth.instance().openSynth();
int usqTempo = 60000000 / 120;
long previousTick = 0;
long timePosition = 0;
MidiToAudioWriter.sort(events);
Receiver receiver = MidiToAudioSynth.instance().getReceiver();
AudioInputStream stream = MidiToAudioSynth.instance().getStream();
for (final MidiEvent event : events) {
MidiMessage msg = event.getMessage();
timePosition += ((event.getTick() - previousTick) * usqTempo)
/ TGDuration.QUARTER_TIME;
if (msg instanceof MetaMessage) {
if (((MetaMessage) msg).getType() == 0x51) {
byte[] data = ((MetaMessage) msg).getData();
usqTempo = ((data[0] & 0xff) << 16) | ((data[1] & 0xff) << 8)
| (data[2] & 0xff);
}
} else {
receiver.send(msg, timePosition);
}
previousTick = event.getTick();
}
long duration = (long) (stream.getFormat().getFrameRate() * ((timePosition / 1000000.0)));
AudioInputStream srcStream = new AudioInputStream(stream, stream
.getFormat(), duration);
AudioInputStream dstStream = AudioSystem.getAudioInputStream(settings
.getFormat(), srcStream);
AudioSystem.write(new AudioInputStream(dstStream, dstStream.getFormat(),
duration), settings.getType(), out);
dstStream.close();
srcStream.close();
MidiToAudioSynth.instance().closeSynth();
}
}