use of com.xenoage.utils.math.Fraction in project Zong by Xenoage.
the class VoicesBeatOffsetterTest method createVoiceSpacings.
/**
* Create {@link VoiceSpacing}s for the first measure column
* of the given {@link Score}.
*/
private LinkedList<VoiceSpacing> createVoiceSpacings(Score score) {
LinkedList<VoiceSpacing> ret = new LinkedList<>();
for (int iStaff : range(0, score.getStavesCount() - 1)) {
Measure measure = score.getMeasure(atMeasure(iStaff, 0));
for (Voice voice : measure.getVoices()) {
Fraction beat = Companion.fr(0);
ArrayList<ElementSpacing> se = alist();
float offset = 0;
for (VoiceElement e : voice.getElements()) {
// compute width
float width = 0;
if (e.getDuration().equals(Companion.get_0()))
width = width_grace;
else if (e.getDuration().equals(dur_1_8))
width = width_1_8;
else if (e.getDuration().equals(dur_1_6))
width = width_1_6;
else if (e.getDuration().equals(dur_1_4))
width = width_1_4;
else if (e.getDuration().equals(dur_3_8))
width = width_3_8;
else if (e.getDuration().equals(dur_1_2))
width = width_1_2;
else if (e.getDuration().equals(dur_1_1))
width = width_1_1;
// create spacing element with offset
se.add(new ChordSpacing(new ChordNotation((Chord) e), beat, offset));
beat = beat.add(e.getDuration());
offset += width;
}
se.add(new BorderSpacing(beat, offset));
ret.add(new VoiceSpacing(voice, score.getFormat().getInterlineSpace(), se));
}
}
return ret;
}
use of com.xenoage.utils.math.Fraction in project Zong by Xenoage.
the class DefaultTexts method getTempoTextNotNull.
public static FormattedText getTempoTextNotNull(Tempo tempo, SymbolPool symbolPool) {
FormattedTextStyle style = FormattedTextStyle.Companion.getDefaultStyle();
if (tempo.getText() != null) {
// use custom text
return styleText(tempo.getText(), style);
} else {
// show meaning, e.g. "♩ = 120"
CList<FormattedTextElement> elements = clist();
Fraction beat = tempo.getBaseBeat();
if (beat.equals(Companion.fr(1, 4))) {
elements.add(new FormattedTextSymbol(symbolPool.getSymbol(CommonSymbol.TextNoteQuarter), /* TODO staffStamping.is * FONT_SIZE_IN_IS */
12, FormattedTextStyle.Companion.getDefaultColor()));
} else if (beat.equals(Companion.fr(1, 2))) {
elements.add(new FormattedTextSymbol(symbolPool.getSymbol(CommonSymbol.TextNoteHalf), /* staffStamping.is * FONT_SIZE_IN_IS */
12, FormattedTextStyle.Companion.getDefaultColor()));
} else {
elements.add(new FormattedTextString(beat.toString(), style));
}
elements.add(new FormattedTextString(" = " + tempo.getBeatsPerMinute(), style));
FormattedTextParagraph paragraph = new FormattedTextParagraph(elements, Alignment.Left);
return Companion.fText(paragraph);
}
}
use of com.xenoage.utils.math.Fraction in project Zong by Xenoage.
the class StemNotatorTest method testPitch.
private void testPitch(Pitch[] pitches, float start, float end) {
MusicContext context = MusicContext.Companion.getSimpleInstance();
Chord chord;
NotesNotation chordNotesAlignment;
StemNotation chordStemAlignment;
Fraction fraction = Companion.fr(1, 1);
chord = ChordFactory.chord(pitches, fraction);
ChordLps linepositions = new ChordLps(chord, context);
StemDirection stemDirection = singleStemDirector.compute(linepositions, 5);
chordNotesAlignment = notesNotator.compute(chord, stemDirection, defaultChordWidthsNormal, context);
chordStemAlignment = testee.compute(Stem.Companion.getDefaultStem(), chordNotesAlignment.getLps(), stemDirection, 0, Companion.getStaff5Lines(), 1);
assertEquals(start, chordStemAlignment.startSlp.lp, Delta.DELTA_FLOAT);
assertEquals(end, chordStemAlignment.endSlp.lp, Delta.DELTA_FLOAT);
}
use of com.xenoage.utils.math.Fraction in project Zong by Xenoage.
the class CursorOutput method write.
public JsonObject write(ScoreDoc doc) {
JsonObject ret = new JsonObject();
// create midi sequence and mp mappings
Score score = doc.getScore();
val seq = MidiConverter.convertToSequence(score, optionsForFileExport, new JseMidiSequenceWriter());
// save time map
JsonArray jsonMPs = new JsonArray();
val timeMap = seq.getTimeMap();
for (int iRep : range(timeMap.getRepetitionsCount())) {
for (val time : timeMap.getTimesSorted(iRep)) {
val midiTime = timeMap.getByRepTime(iRep, time);
JsonObject jsonMP = new JsonObject();
jsonMP.addProperty("measure", time.measure);
jsonMP.addProperty("beat", "" + time.beat);
jsonMP.addProperty("ms", midiTime.ms);
jsonMPs.add(jsonMP);
}
}
ret.add("mps", jsonMPs);
// collect data
int measuresCount = score.getMeasuresCount();
ArrayList<System> systems = new ArrayList<>();
ArrayList<Measure> measures = new ArrayList<>();
for (int i = 0; i < measuresCount; i++) {
measures.add(new Measure());
}
int systemCount = 0;
Layout layout = doc.getLayout();
for (int iPage : range(layout.getPages())) {
Page page = layout.getPages().get(iPage);
Size2f pageSize = page.getFormat().getSize();
for (Frame frame : page.getFrames()) {
if (frame instanceof ScoreFrame) {
Point2f absPos = frame.getAbsolutePosition();
float offsetX = absPos.x - frame.getSize().width / 2;
float offsetY = absPos.y - frame.getSize().height / 2;
ScoreFrameLayout sfl = ((ScoreFrame) frame).getScoreFrameLayout();
for (SystemSpacing systemSpacing : sfl.getFrameSpacing().getSystems()) {
// read system data
int systemIndex = systemCount + systemSpacing.getSystemIndexInFrame();
while (systems.size() - 1 < systemIndex) systems.add(new System());
System system = systems.get(systemIndex);
system.page = iPage;
system.top = (offsetY + systemSpacing.offsetYMm) / pageSize.height;
system.bottom = (offsetY + systemSpacing.offsetYMm + systemSpacing.getHeightMm()) / pageSize.height;
// read measure beats
float systemOffsetX = systemSpacing.marginLeftMm;
for (int iMeasure : systemSpacing.getMeasures()) {
Measure measure = measures.get(iMeasure);
measure.system = systemIndex;
measure.left = (offsetX + systemOffsetX + systemSpacing.getMeasureStartMm(iMeasure)) / pageSize.width;
measure.right = (offsetX + systemOffsetX + systemSpacing.getMeasureEndMm(iMeasure)) / pageSize.width;
for (BeatOffset bo : systemSpacing.getColumn(iMeasure).getBeatOffsets()) {
measure.beats.put(bo.getBeat(), (offsetX + systemOffsetX + bo.getOffsetMm()) / pageSize.width);
}
}
}
systemCount += sfl.getFrameSpacing().getSystems().size();
}
}
}
// save systems
JsonArray jsonSystems = new JsonArray();
for (int i = 0; i < systems.size(); i++) {
System system = systems.get(i);
JsonObject jsonSystem = new JsonObject();
jsonSystem.addProperty("number", i);
jsonSystem.addProperty("page", system.page);
jsonSystem.addProperty("top", system.top);
jsonSystem.addProperty("bottom", system.bottom);
jsonSystems.add(jsonSystem);
}
ret.add("systems", jsonSystems);
// save measures
JsonArray jsonMeasures = new JsonArray();
for (int i = 0; i < measuresCount; i++) {
Measure measure = measures.get(i);
JsonObject jsonMeasure = new JsonObject();
jsonMeasure.addProperty("number", i);
jsonMeasure.addProperty("system", measure.system);
jsonMeasure.addProperty("left", measure.left);
jsonMeasure.addProperty("right", measure.right);
// beats
JsonArray jsonBeats = new JsonArray();
ArrayList<Fraction> sortedBeats = new ArrayList<>(measure.beats.keySet());
Collections.sort(sortedBeats);
for (Fraction beat : sortedBeats) {
JsonObject jsonBeat = new JsonObject();
jsonBeat.addProperty("at", "" + beat);
jsonBeat.addProperty("x", measure.beats.get(beat));
jsonBeats.add(jsonBeat);
}
jsonMeasure.add("beats", jsonBeats);
jsonMeasures.add(jsonMeasure);
}
ret.add("measures", jsonMeasures);
// save time cursors
JsonArray jsonTCs = new JsonArray();
for (int iRep : range(timeMap.getRepetitionsCount())) {
for (val time : timeMap.getTimesSorted(iRep)) {
val midiTime = timeMap.getByRepTime(iRep, time);
JsonObject jsonTC = new JsonObject();
jsonTC.addProperty("time", midiTime.ms);
Measure measure = measures.get(time.measure);
System system = systems.get(measure.system);
jsonTC.addProperty("page", system.page);
jsonTC.addProperty("top", system.top);
jsonTC.addProperty("left", measure.beats.get(time.beat));
jsonTC.addProperty("bottom", system.bottom);
jsonTCs.add(jsonTC);
}
}
ret.add("timecursors", jsonTCs);
return ret;
}
use of com.xenoage.utils.math.Fraction in project Zong by Xenoage.
the class ChordReader method readFirstNote.
private void readFirstNote() {
mxlFirstNote = mxlNotes.get(0);
MxlNoteContentType mxlFirstNoteType = mxlFirstNote.getContent().getNoteContentType();
// type of chord/rest
// (unpitched is still unsupported)
MxlFullNote mxlFirstFullNote = mxlFirstNote.getContent().getFullNote();
MxlNormalNote mxlFirstNormalNote = null;
MxlCueNote mxlFirstCueNote = null;
MxlGraceNote mxlFirstGraceNote = null;
boolean isCue = false;
boolean isGrace = false;
if (mxlFirstNoteType == MxlNoteContentType.Normal) {
mxlFirstNormalNote = (MxlNormalNote) mxlNotes.get(0).getContent();
} else if (mxlFirstNoteType == MxlNoteContentType.Cue) {
mxlFirstCueNote = (MxlCueNote) mxlNotes.get(0).getContent();
isCue = true;
} else if (mxlFirstNoteType == MxlNoteContentType.Grace) {
mxlFirstGraceNote = (MxlGraceNote) mxlNotes.get(0).getContent();
isGrace = true;
// may also be true later, see (TODO) "Zong-Library/Discussions/MusicXML/Note - cue vs grace.txt"
isCue = false;
}
MxlFullNoteContentType mxlFNCType = mxlFirstFullNote.getContent().getFullNoteContentType();
// duration. here, the first duration is the duration of the whole chord.
Fraction duration = Companion.get_0();
if (mxlFirstNormalNote != null) {
duration = readDuration(mxlFirstNormalNote.getDuration(), context.getDivisions());
} else if (mxlFirstCueNote != null) {
duration = readDuration(mxlFirstCueNote.getDuration(), context.getDivisions());
}
// when duration of normal note is 0, ignore the chord
if (false == isGrace && false == duration.isGreater0()) {
context.reportError("duration of chord is 0");
return;
}
// create new chord or rest
if (mxlFNCType == MxlFullNoteContentType.Pitch || mxlFNCType == MxlFullNoteContentType.Unpitched) {
// create a chord
Pitch pitch;
if (mxlFNCType == MxlFullNoteContentType.Pitch)
pitch = ((MxlPitch) mxlFirstFullNote.getContent()).getPitch();
else
// TODO (ZONG-96): better support for unpitched notes
pitch = Pitch.Companion.pi(0, 4);
Grace grace = null;
if (mxlFirstGraceNote != null) {
// read grace duration from note-type ("eighth", "16th", ...)
Fraction graceDuration = Companion.fr(1, 8);
if (mxlFirstNote.getNoteType() != null)
graceDuration = mxlFirstNote.getNoteType().getDuration();
boolean slash = mxlFirstGraceNote.getSlash() == MxlYesNo.Yes;
grace = new Grace(slash, graceDuration);
chord = new Chord(alist(new Note(pitch)), grace);
} else {
chord = new Chord(alist(new Note(pitch)), duration);
}
chord.setCue(isCue);
chordOrRest = chord;
} else if (mxlFNCType == MxlFullNoteContentType.Rest) {
// create a rest
Rest rest = new Rest(duration);
rest.setCue(isCue);
chordOrRest = rest;
}
}
Aggregations