package com.moseph.mra.midi;
import java.text.DecimalFormat;
import java.util.*;
import static com.moseph.mra.midi.MidiUtilities.*;
import javax.sound.midi.*;
import com.moseph.mra.*;
/**
* Reads information out of a Track, and returns it as Fragments
* @author s0239182
*
*/
public class TrackToFragment
{
Map<Integer,Vector<Note>> openNotes = new HashMap<Integer,Vector<Note>>();
Track track;
SongInfo songInfo;
int currentEvent = 0;
static DecimalFormat df = new DecimalFormat( "00.000");
Fragment fragment;
public TrackToFragment( Track t, SongInfo s )
{
this( t, s, new Fragment() );
}
public TrackToFragment( Track t, SongInfo s, Fragment fragment )
{
this.track = t;
this.songInfo = s;
this.fragment = fragment;
}
public void addToFragment()
{
int numEvents = track.size();
//openHangingNotes( fragment );
System.out.println( "Adding to fragment from " + currentEvent + " to " + numEvents + " events" );
while( currentEvent < numEvents )
{
try
{
MidiEvent e = track.get( currentEvent );
//System.out.println( "Adding event at " + df.format( songInfo.getEventBeat( e ) ) + "<" + e.getTick() + ">: " + eventToString( e ) + "("+ currentEvent + ")" );
MidiMessage m = e.getMessage();
if( isNoteOnMessage( m ) )
{
addNoteEvent( e, fragment );
}
else if( isNoteOffMessage( m ) )
{
closeNotes( e );
}
currentEvent++;
}
catch( Exception e )
{
e.printStackTrace();
}
}
System.out.println( "Done adding to fragment");
}
public boolean addNoteEvent( MidiEvent e, Fragment f )
{
double noteBeat = songInfo.getEventBeat( e );
int noteNumber = ((ShortMessage)e.getMessage()).getData1();
int noteVelocity = ((ShortMessage)e.getMessage()).getData2();
double vel = (double)noteVelocity / 127;
Note n = createNote( noteBeat, noteNumber, vel );
n.setEvent( e );
f.addNote( n );
openNote( n );
return true;
}
Note createNote( double noteBeat, int noteNumber, double vel )
{
return new Note( noteBeat, noteNumber, vel );
}
public void closeNotes( MidiEvent e )
{
ShortMessage sm = (ShortMessage)e.getMessage();
//System.out.println( "Closing notes: " + sm.getData1() );
int pitch = ((ShortMessage)e.getMessage()).getData1();
Vector<Note> v = getNoteVector( sm.getData1() );
for( Note n : v )
if( n.getPitchNumber() == pitch )
{
closeNoteWithEvent( n, e );
//System.out.println( "Closing note!");
}
v.clear();
}
public void openNote( Note n )
{
//System.out.println( "Opening note " + n.getPitchNumber() );
getNoteVector( n.getPitchNumber() ).add( n );
}
Vector<Note> getNoteVector( int pitch )
{
if( openNotes.containsKey( pitch ) )
return openNotes.get( pitch );
Vector<Note> notes = new Vector<Note>();
openNotes.put( pitch, notes );
return notes;
}
void closeNoteWithEvent( Note n, MidiEvent e )
{
if( n.getStartEvent() != null )
{
double endTime = songInfo.getEventBeat( e );
double duration = ( endTime - n.getOnset() );
n.close( duration );
}
}
void truncateNotes( Fragment f, double length )
{
for( Vector<Note> notes : openNotes.values() )
for( Note n : notes )
n.setEndTime( length );
}
void openHangingNotes( Fragment f )
{
for( Vector<Note> notes : openNotes.values() )
for( int i = 0; i < notes.size(); i++ )
{
Note n = notes.get( i );
//System.out.println( "Opening hanging note " + n.getPitchNumber() );
Note n2 = n.clone();
n2.setOnset( 0.0 );
n2.setStartsBefore( true );
n2.setLongerThan( true );
notes.set( i, n2 );
f.addNote( n2 );
}
}
public double gotTill()
{
return songInfo.getTickBeat( track.ticks() );
}
public Fragment getChunk( double start, double end )
{
System.out.println( "Getting chunk from " + start + " to " + end );
return fragment.copyChunk( start, end );
}
public double beatLength()
{
return fragment.getLength();
}
}