examples.be.tarsos.dsp.example.catify.MidiParser Maven / Gradle / Ivy
The newest version!
/*
* _______ _____ _____ _____
* |__ __| | __ \ / ____| __ \
* | | __ _ _ __ ___ ___ ___| | | | (___ | |__) |
* | |/ _` | '__/ __|/ _ \/ __| | | |\___ \| ___/
* | | (_| | | \__ \ (_) \__ \ |__| |____) | |
* |_|\__,_|_| |___/\___/|___/_____/|_____/|_|
*
* -------------------------------------------------------------
*
* TarsosDSP is developed by Joren Six at IPEM, University Ghent
*
* -------------------------------------------------------------
*
* Info: http://0110.be/tag/TarsosDSP
* Github: https://github.com/JorenSix/TarsosDSP
* Releases: http://0110.be/releases/TarsosDSP/
*
* TarsosDSP includes modified source code by various authors,
* for credits and info, see README.
*
*/
package be.tarsos.dsp.example.catify;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MidiEvent;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.Sequence;
public class MidiParser {
private Sequence seq;
private int currentTrack;
private ArrayList nextMessageOf;
private List temporaryMidiNotes;
private List midiNotes;
public MidiParser(File midiFile) throws InvalidMidiDataException, IOException{
seq = MidiSystem.getSequence(midiFile);
}
public List generateNoteInfo(){
temporaryMidiNotes = new ArrayList();
midiNotes = new ArrayList();
nextMessageOf = new ArrayList();
currentTrack = 0;
convertMidi2RealTime(seq);
return midiNotes;
}
private void convertMidi2RealTime(Sequence seq) {
double currentTempo = 500000;
int tickOfTempoChange = 0;
double msb4 = 0;
for (int track = 0; track < seq.getTracks().length; track++){
nextMessageOf.add(0);
}
MidiEvent nextEvent;
while ((nextEvent = getNextEvent()) != null) {
int tick = (int) nextEvent.getTick();
if (noteIsOff(nextEvent)) {
double time = (msb4 + (((currentTempo / seq.getResolution()) / 1000) * (tick - tickOfTempoChange)));
int stop = (int) (time + 0.5);
int midiNote = ((int) nextEvent.getMessage().getMessage()[1] & 0xFF);
MidiNoteInfo midiNoteInfo = null;
for(MidiNoteInfo s : temporaryMidiNotes){
if(s.getMidiNote()==midiNote){
midiNoteInfo = s;
}
}
if(midiNoteInfo==null){
System.err.println("Note off without note on...");
}else{
temporaryMidiNotes.remove(midiNoteInfo);
midiNoteInfo.setStop(stop);
midiNotes.add(midiNoteInfo);
}
} else if (noteIsOn(nextEvent)) {
double time = (msb4 + (((currentTempo / seq.getResolution()) / 1000) * (tick - tickOfTempoChange)));
int start = (int) (time + 0.5);
int midiNote = ((int) nextEvent.getMessage().getMessage()[1] & 0xFF);
int velocity = ((int) nextEvent.getMessage().getMessage()[2] & 0xFF);
//System.out.println("track=" + currentTrack + " tick=" + tick + " time=" + start + "ms " + " note " + midiNote + " on" + " velocity " + velocity);
temporaryMidiNotes.add(new MidiNoteInfo(start,midiNote, velocity));
} else if (changeTemp(nextEvent)) {
String a = (Integer.toHexString((int) nextEvent.getMessage()
.getMessage()[3] & 0xFF));
String b = (Integer.toHexString((int) nextEvent.getMessage()
.getMessage()[4] & 0xFF));
String c = (Integer.toHexString((int) nextEvent.getMessage()
.getMessage()[5] & 0xFF));
if (a.length() == 1)
a = ("0" + a);
if (b.length() == 1)
b = ("0" + b);
if (c.length() == 1)
c = ("0" + c);
String whole = a + b + c;
int newTempo = Integer.parseInt(whole, 16);
double newTime = (currentTempo / seq.getResolution())
* (tick - tickOfTempoChange);
msb4 += (newTime / 1000);
tickOfTempoChange = tick;
currentTempo = newTempo;
}
}
}
private MidiEvent getNextEvent() {
ArrayList nextEvent = new ArrayList();
ArrayList trackOfNextEvent = new ArrayList();
for (int track = 0; track < seq.getTracks().length; track++) {
if (seq.getTracks()[track].size() - 1 > (nextMessageOf.get(track))) {
nextEvent.add(seq.getTracks()[track].get(nextMessageOf
.get(track)));
trackOfNextEvent.add(track);
}
}
if (nextEvent.size() == 0)
return null;
int closestMessage = 0;
int smallestTick = (int) nextEvent.get(0).getTick();
for (int trialMessage = 1; trialMessage < nextEvent.size(); trialMessage++) {
if ((int) nextEvent.get(trialMessage).getTick() < smallestTick) {
smallestTick = (int) nextEvent.get(trialMessage).getTick();
closestMessage = trialMessage;
}
}
currentTrack = trackOfNextEvent.get(closestMessage);
nextMessageOf.set(currentTrack, (nextMessageOf.get(currentTrack) + 1));
return nextEvent.get(closestMessage);
}
private static boolean noteIsOff(MidiEvent event) {
if (Integer.toString((int) event.getMessage().getStatus(), 16)
.toUpperCase().charAt(0) == '8'
|| (noteIsOn(event) && event.getMessage().getLength() >= 3 && ((int) event
.getMessage().getMessage()[2] & 0xFF) == 0))
return true;
return false;
}
private static boolean noteIsOn(MidiEvent event) {
if (Integer.toString(event.getMessage().getStatus(), 16).toUpperCase()
.charAt(0) == '9')
return true;
return false;
}
private static boolean changeTemp(MidiEvent event) {
if ((int) Integer.valueOf(
("" + Integer
.toString((int) event.getMessage().getStatus(), 16)
.toUpperCase().charAt(0)), 16) == 15
&& (int) Integer.valueOf(
("" + ((String) (Integer.toString((int) event
.getMessage().getStatus(), 16).toUpperCase()))
.charAt(1)), 16) == 15
&& Integer
.toString((int) event.getMessage().getMessage()[1], 16)
.toUpperCase().length() == 2
&& Integer
.toString((int) event.getMessage().getMessage()[1], 16)
.toUpperCase().equals("51")
&& Integer
.toString((int) event.getMessage().getMessage()[2], 16)
.toUpperCase().equals("3"))
return true;
return false;
}
}