//---------------------------------------------------
int partCount = 0;
Enumeration aEnum = score.getPartList().elements();
while(aEnum.hasMoreElements()){
Track smfTrack = new Track();
Part inst = (Part) aEnum.nextElement();
System.out.print(" Part "+ partCount + " '" + inst.getTitle() +
"' to SMF Track on Ch. " + inst.getChannel() + ": ");
partCount++;
// set up tempo difference between score and track - if any
if(inst.getTempo() != Part.DEFAULT_TEMPO) partTempoMultiplier =
scoreTempo / inst.getTempo();
else partTempoMultiplier = 1.0;
//System.out.println("partTempoMultiplier = " + partTempoMultiplier);
//order phrases based on their startTimes
phraseNumb = inst.getPhraseList().size();
for(int i=0; i< phraseNumb; i++){
phrase1 = (Phrase) inst.getPhraseList().elementAt(i);
for(int j=0; j<phraseNumb; j++){
phrase2 = (Phrase)inst.getPhraseList().elementAt(j);
if(phrase2.getStartTime() > phrase1.getStartTime()){
inst.getPhraseList().setElementAt( phrase2, i );
inst.getPhraseList().setElementAt( phrase1, j );
break;
}
}
}
//break Note objects into NoteStart's and NoteEnd's
//as well as combining all phrases into one list
// HashMap midiEvents = new HashMap();
class EventPair{public double time; public Event ev; public EventPair(double t, Event e){time = t; ev = e;}};
LinkedList<EventPair> midiEvents = new LinkedList<EventPair>();
/*if(inst.getTempo() != Part.DEFAULT_TEMPO){
//System.out.println("Adding part tempo");
midiEvents.add(new EventPair(0, new TempoEvent(inst.getTempo())));
} */
//if this part has a Program Change value then set it
if(inst.getInstrument() != NO_INSTRUMENT){
//System.out.println("Instrument change no. " + inst.getInstrument());
midiEvents.add(new EventPair(0, new PChange((short) inst.getInstrument(),(short) inst.getChannel(),0)));
}
if(inst.getNumerator() != NO_NUMERATOR){
midiEvents.add(new EventPair(0, new TimeSig(inst.getNumerator(),inst.getDenominator())));
}
if(inst.getKeySignature() != NO_KEY_SIGNATURE){
midiEvents.add(new EventPair(0, new KeySig(inst.getKeySignature(),inst.getKeyQuality())));
}
Enumeration partEnum = inst.getPhraseList().elements();
double max = 0;
double startTime = 0.0;
double offsetValue = 0.0;
int phraseCounter = 0;
while(partEnum.hasMoreElements()) {
Phrase phrase = (Phrase) partEnum.nextElement();
Enumeration phraseEnum = phrase.getNoteList().elements();
startTime = phrase.getStartTime() * partTempoMultiplier;
if(phrase.getInstrument() != NO_INSTRUMENT){
midiEvents.add(new EventPair(0, new PChange((short)phrase.getInstrument(),(short)inst.getChannel(),0)));
}
if(phrase.getTempo() != Phrase.DEFAULT_TEMPO) {
phraseTempoMultiplier = scoreTempo / phrase.getTempo(); //(scoreTempo * partTempoMultiplier) / phrase.getTempo();
} else {
phraseTempoMultiplier = partTempoMultiplier;
}
////////////////////////////////////////////////
int noteCounter = 0;
//System.out.println();
System.out.print(" Phrase " + phraseCounter++ +":");
// set a silly starting value to force and initial pan cc event
double pan = -1.0;
resetTicker(); // zero the ppqn error calculator
while(phraseEnum.hasMoreElements()){
Note note = (Note) phraseEnum.nextElement();
offsetValue = note.getOffset();
// add a pan control change if required
if(note.getPan() != pan) {
pan = note.getPan();
midiEvents.add(new EventPair(startTime + offsetValue, new CChange((short)10,(short)(pan * 127), (short)inst.getChannel(),0)));
}
//check for frequency rather than MIDI notes
int pitch = 0;
if (note.getPitchType() == Note.FREQUENCY) {
System.err.println("jMusic warning: converting note frequency to the closest MIDI pitch for SMF.");
//System.exit(1);
pitch = Note.freqToMidiPitch(note.getFrequency());
} else pitch = note.getPitch();
if(pitch != REST) {
midiEvents.add(new EventPair(new Double(startTime + offsetValue),new NoteOn((short)pitch,(short)note.getDynamic(),(short)inst.getChannel(),0)));
// Add a NoteOn for the END of the note with 0 dynamic, as recommended.
//create a timing event at the end of the notes duration
double endTime = startTime + (note.getDuration() * phraseTempoMultiplier);
// Add the note-off time to the list
midiEvents.add(new EventPair(new Double(endTime + offsetValue),new NoteOn((short)pitch, (short)0, (short)inst.getChannel(),0)));
}
// move the note-on time forward by the rhythmic value
startTime += tickRounder(note.getRhythmValue() * phraseTempoMultiplier); //time between start times
System.out.print("."); // completed a note
}