use of com.xenoage.utils.math.Fraction in project Zong by Xenoage.
the class MidiConverter method writeMetronomeTrack.
/**
* Writes the metronome beats into the metronome track.
*/
private void writeMetronomeTrack(int track) {
int strongBeatNote = options.midiSettings.metronomeStrongBeatNote;
int weakBeatNote = options.midiSettings.metronomeWeakBeatNote;
for (int iRep : range(repetitions)) {
val rep = repetitions.get(iRep);
for (int iMeasure : range(rep.start.getMeasure(), rep.end.getMeasure())) {
TimeSignature timeSig = score.getHeader().getTimeAtOrBefore(iMeasure);
Fraction startBeat = (rep.start.getMeasure() == iMeasure ? rep.start.getBeat() : Companion.get_0());
Fraction endBeat = (rep.end.getMeasure() == iMeasure ? rep.end.getBeat() : score.getMeasureBeats(iMeasure));
if (timeSig != null) {
boolean[] accentuation = timeSig.getType().getBeatsAccentuation();
int timeDenominator = timeSig.getType().getDenominator();
long measureStartTick = timeMap.getByRepTime(iRep, Companion.time(iMeasure, Companion.get_0())).tick;
for (int beatNumerator : range(timeSig.getType().getNumerator())) {
// compute start and stop tick
val beat = Companion.fr(beatNumerator, timeDenominator);
val time = Companion.time(iMeasure, beat);
if (false == rep.contains(time))
continue;
long tickStart = measureStartTick + durationToTick(Companion.fr(beatNumerator, timeDenominator), resolution);
long tickStop = tickStart + durationToTick(Companion.fr(1, timeDenominator), resolution);
// write metronome note
int note = (accentuation[beatNumerator] ? strongBeatNote : weakBeatNote);
int velocity = midiMaxValue;
writer.writeNote(track, channel10, tickStart, note, true, velocity);
writer.writeNote(track, channel10, tickStop, note, false, 0);
}
}
}
}
}
use of com.xenoage.utils.math.Fraction in project Zong by Xenoage.
the class RepetitionsFinder method collectJumps.
/**
* Creates the list of jumps for this score.
*/
private void collectJumps() {
// if not null, the next segno will jump back to this one
Segno lastSegno = null;
// in the next volta group, jump to this repeat number
int lastVoltaCounter = 1;
Fraction measureStartBeat = null;
nextMeasure: for (currentMeasureIndex = 0; currentMeasureIndex < score.getMeasuresCount(); ) {
val measure = score.getColumnHeader(currentMeasureIndex);
// are we stuck within an endless loop? then do not jump at all.
if (jumps.size() > maxJumps) {
jumps.clear();
return;
}
// enter a volta
if (voltaGroups.getVoltaGroupStartingAt(currentMeasureIndex) != null)
if (processVolta())
continue nextMeasure;
// inner backward repeat barlines
if (isWithRepeats) {
for (val e : getInnerBarlines()) {
val innerBarline = e.getElement();
val eTime = Companion.time(currentMeasureIndex, e.getBeat());
if (innerBarline.getRepeat().isBackward())
if (processBackwardRepeat(innerBarline, eTime))
continue nextMeasure;
}
}
// backward repeat at measure end
val endBarline = measure.getEndBarline();
val endTime = Companion.time(currentMeasureIndex + 1, Companion.get_0());
if (isWithRepeats && endBarline != null) {
if (endBarline.getRepeat().isBackward()) {
// ignore it at the end of the final volta of a volta group, otherwise we are stuck in an endless loop
if (false == isFinalVoltaAt(currentMeasureIndex))
if (processBackwardRepeat(endBarline, endTime))
continue nextMeasure;
}
}
// origin navigation sign
// we read them after the backward repeat barlines. e.g. when there is both
// a repeat and a "to coda", we first play the repeat and then the "to coda".
val sign = measure.getNavigationOrigin();
if (sign != null) {
// da capo ,
if (MusicElementType.DaCapo.is(sign))
if (processDaCapo((DaCapo) sign))
continue nextMeasure;
// target segno
if (MusicElementType.Segno.is(sign))
if (processSegno((Segno) sign))
continue nextMeasure;
// to coda
if (MusicElementType.Coda.is(sign))
if (processCoda((Coda) sign))
continue nextMeasure;
}
// no jump found in this measure, continue
currentMeasureIndex++;
currentMeasureStartBeat = null;
}
}
use of com.xenoage.utils.math.Fraction in project Zong by Xenoage.
the class SystemSpacing method getMpAt.
/**
* Gets the {@link MP} at the given horizontal position in mm.
* If the given staff is {@link MP#unknown}, all beats of the column
* are used, otherwise only the beats used by the given staff.
*
* If it is between two beats (which will be true almost ever), the
* the right mark is selected (like it is usual e.g. in text
* processing applications). If it is behind all known beats of the
* hit measure, the last known beat is returned.
*
* If it is not within the boundaries of a measure, {@link MP#unknownMp} is returned.
*/
public MP getMpAt(float xMm, int staff) {
// find the measure
int measureIndex = getSystemMeasureIndexAt(xMm);
float xMmInMeasure = xMm - getMeasureStartMm(measureIndex);
// when measure was not found, return null
if (measureIndex == unknown)
return unknownMp;
// get the beat at the given position
Fraction beat = columns.get(measureIndex).getBeatAt(xMmInMeasure, staff);
return atBeat(staff, measureIndex, unknown, beat);
}
use of com.xenoage.utils.math.Fraction in project Zong by Xenoage.
the class MidiVelocityConverterTry method createTestScore.
public static Score createTestScore() {
Score ret = new Score();
Instrument instr = Instrument.Companion.getDefaultInstrument();
Part pianoPart = new Part("Test", "T", 1, ilist(instr));
new PartAdd(ret, pianoPart, 0, null).execute();
Cursor cursor = new Cursor(ret, mp0, true);
cursor.write((ColumnElement) new TraditionalKey(-3));
cursor.write((ColumnElement) new TimeSignature(Companion.timeType(3, 4)));
cursor.write(new Clef(ClefType.Companion.getClefTreble()));
Fraction f4 = Companion.fr(1, 4);
Chord attachC;
cursor.write(attachC = chord(f4, Pitch.Companion.pi(Pitch.Companion.getG(), 4)));
attachC.addDirection(new Dynamic(DynamicValue.pp));
cursor.write(attachC = chord(f4, Pitch.Companion.pi(Pitch.Companion.getA(), 4)));
attachC.addDirection(new Dynamic(DynamicValue.ff));
cursor.write(attachC = chord(f4, Pitch.Companion.pi(Pitch.Companion.getG(), 4)));
attachC.addDirection(new Dynamic(DynamicValue.sfp));
/*
Chord chord;
Voice voice = measure.getVoices().get(0);
chord = voice.addNote(pi'G', 0, 4), fr(1, 4));
chord.addDirection(new Dynamic(DynamicsType.pp));
chord = voice.addNote(pi'A', 0, 4), fr(1, 4));
chord.addDirection(new Dynamic(DynamicsType.ff));
chord = voice.addNote(pi'G', 0, 4), fr(1, 4));
chord.addDirection(new Dynamic(DynamicsType.sfp));
*/
cursor.setMp(mp0.withVoice(1));
cursor.write(attachC = chord(f4, Pitch.Companion.pi(Pitch.Companion.getC(), 4)));
attachC.addDirection(new Dynamic(DynamicValue.fff));
/*
voice = measure.addVoice();
chord = voice.addNote(pi'C', 0, 4), fr(1, 4));
chord.addDirection(new Dynamic(DynamicsType.fff));
*/
cursor.setMp(mp0.withMeasure(1));
cursor.write(attachC = chord(f4, Pitch.Companion.pi(Pitch.Companion.getG(), 4)));
// cursor.withScore(ScoreController.attachElement(cursor.getScore(), attachC, new Dynamic(DynamicsType.pp)));
cursor.write(attachC = chord(f4, Pitch.Companion.pi(Pitch.Companion.getA(), 4)));
attachC.addDirection(new Dynamic(DynamicValue.pp));
cursor.write(attachC = chord(f4, Pitch.Companion.pi(Pitch.Companion.getG(), 4)));
attachC.addDirection(new Dynamic(DynamicValue.pp));
cursor.setMp(cursor.getMP().withElement(0).withVoice(1));
cursor.write(attachC = chord(f4, Pitch.Companion.pi(Pitch.Companion.getC(), 5)));
/*
measure = staff.getMeasures().get(1);
voice = measure.getVoices().get(0);
chord = voice.addNote(pi'G', 0, 4), fr(1, 4));
//chord.addDirection(new Dynamic(DynamicsType.pp));
chord = voice.addNote(pi'A', 0, 4), fr(1, 4));
chord.addDirection(new Dynamic(DynamicsType.pp));
chord = voice.addNote(pi'G', 0, 4), fr(1, 4));
chord.addDirection(new Dynamic(DynamicsType.pp));
voice = measure.addVoice();
chord = voice.addNote(pi'C', 0, 5), fr(1, 4));
*/
cursor.setMp(mp0.withMeasure(2));
cursor.write(attachC = chord(f4, Pitch.Companion.pi(Pitch.Companion.getG(), 4)));
attachC.addDirection(new Dynamic(DynamicValue.sfz));
cursor.write(chord(f4, Pitch.Companion.pi(Pitch.Companion.getA(), 4)));
// cursor = cursor.withScore(ScoreController.attachElement(cursor.getScore(), attachC, new Dynamic(DynamicsType.pp)));
cursor.write(chord(f4, Pitch.Companion.pi(Pitch.Companion.getG(), 4)));
// cursor = cursor.withScore(ScoreController.attachElement(cursor.getScore(), attachC, new Dynamic(DynamicsType.pp)));
cursor.setMp(mp0.withMeasure(2).withVoice(2));
cursor.write(chord(f4, Pitch.Companion.pi(Pitch.Companion.getC(), 5)));
/*
measure = staff.getMeasures().get(2);
voice = measure.getVoices().get(0);
chord = voice.addNote(pi'G', 0, 4), fr(1, 4));
chord.addDirection(new Dynamic(DynamicsType.sfz));
chord = voice.addNote(pi'A', 0, 4), fr(1, 4));
//chord.addDirection(new Dynamic(DynamicsType.pp));
chord = voice.addNote(pi'G', 0, 4), fr(1, 4));
//chord.addDirection(new Dynamic(DynamicsType.pp));
voice = measure.addVoice();
voice = measure.addVoice();
chord = voice.addNote(pi'C',0,5), fr(1,2));
*/
return cursor.getScore();
}
use of com.xenoage.utils.math.Fraction in project Zong by Xenoage.
the class AlignedVoicesSpacer method computeSharedBeats.
/**
* Returns the shared beats of the given {@link ElementSpacing}s and {@link BeatOffset}s.
* If there are no beats used by both lists, an empty list is returned.
*/
public List<BeatOffset> computeSharedBeats(List<ElementSpacing> spacingElements, List<BeatOffset> beatOffsets) {
ArrayList<BeatOffset> ret = alist(Math.min(spacingElements.size(), beatOffsets.size()));
int iElement = 0, iBeat = 0;
Fraction lastAddedBeat = Companion.fr(-1);
while (iElement < spacingElements.size() && iBeat < beatOffsets.size()) {
Fraction elementBeat = spacingElements.get(iElement).beat;
BeatOffset beatOffset = beatOffsets.get(iBeat);
if (elementBeat.equals(beatOffset.beat)) {
if (beatOffset.beat.equals(lastAddedBeat)) {
// when this beat was already added, replace it. the
// rightmost offset is the offset we need.
ret.set(ret.size() - 1, beatOffset);
} else {
ret.add(beatOffset);
}
lastAddedBeat = beatOffset.beat;
iElement++;
} else if (elementBeat.compareTo(beatOffset.beat) > 0) {
iBeat++;
} else {
iElement++;
}
}
return ret;
}
Aggregations