All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy