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