まぁ、何か作ってますよ程度のもの。Java FXとJava Sound APIを使って遊んでるだけです
import javafx.stage.Stage;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.animation.Animation;
import javafx.util.Duration;
import java.io.File;
import java.util.List;
import javax.xml.bind.JAXB;
import javax.sound.midi.Receiver;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.ShortMessage;
import net.d_kami.midi.data.MidiNote;
import net.d_kami.midi.data.MidiTrack;
import net.d_kami.midi.data.MidiMusic;
import javax.sound.midi.InvalidMidiDataException;
public class MidiTest extends Application {
private Receiver receiver;
private Timeline timer;
private int timerCount = 0;
private int bassIndex = 0;
private int drumIndex = 0;
private MidiMusic music;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) throws Exception {
receiver = MidiSystem.getReceiver();
music = JAXB.unmarshal(new File("midi.xml"), MidiMusic.class);
Button button = createMidiButton("8ビート!");
BorderPane pane = new BorderPane();
pane.setCenter(button);
Scene scene = new Scene(pane, 320, 120);
stage.setScene(scene);
stage.show();
}
private Button createMidiButton(String text){
loadProgram();
setTempo(120);
return createButton(text);
}
private Button createButton(String text){
Button button = new Button(text);
button.setOnAction(e -> {
if(timer.getStatus() == Animation.Status.STOPPED){
timer.setCycleCount(160);
timer.play();
}
});
return button;
}
private void setTempo(int bpm){
int duration = 60000 / bpm * 4 / 128;
setTimer(duration);
}
private void setTimer(int duration){
List<MidiTrack> tracks = music.getTracks();
int[] indices = new int[tracks.size()];
timer = new Timeline(new KeyFrame(Duration.millis(duration), event -> {
try{
for(int i = 0; i < tracks.size(); i++){
MidiTrack track = tracks.get(i);
midiEvent(track, duration, indices, i);
}
}catch(InvalidMidiDataException ex){
ex.printStackTrace();
}
timerCount++;
}));
}
private void loadProgram(){
music.getTracks().forEach(track -> {
try{
programChange(track.getNumber(), track.getProgram());
}catch(InvalidMidiDataException e){
e.printStackTrace();
}
});
}
private void programChange(int trackNumber, int program) throws InvalidMidiDataException{
ShortMessage message = new ShortMessage();
message.setMessage(ShortMessage.PROGRAM_CHANGE, trackNumber, program, 0);
receiver.send(message, -1);
}
private void midiEvent(MidiTrack track, int duration, int[] indices, int i) throws InvalidMidiDataException{
List<MidiNote> notes = track.getNotes();
if(indices[i] < notes.size()){
MidiNote note = notes.get(indices[i]);
if(duration * timerCount > note.getPosition()){
note(track.getNumber(), note.getType(), note.getNote(), note.getVelocity());
indices[i]++;
}
}
}
private void note(int trackNumber, int type, int note, int velocity) throws InvalidMidiDataException{
ShortMessage message = new ShortMessage();
message.setMessage(type, trackNumber, note, velocity);
receiver.send(message, -1);
}
}