use of com.xenoage.zong.core.music.clef.Clef in project Zong by Xenoage.
the class ScoreTest method createTestScoreClefsKeys.
/**
* Creates a score with a single staff, two measures,
* and a number of clefs, keys and chords.
* The score, the list of clefs and the list of keys is returned.
*/
private Tuple3<Score, List<ClefType>, List<Key>> createTestScoreClefsKeys() {
// create two measures:
// clef-g, key-Gmaj, C#1/4, clef-f, Db1/4, clef-g, key-Fmaj, Cnat1/4 |
// C#1/4, key-Cmaj, clef-f, C2/4.
Score score = ScoreFactory.create1Staff();
new MeasureAdd(score, 1).execute();
List<ClefType> clefs = alist();
List<Key> keys = alist();
ClefType c;
Key k;
// measure 0
Measure measure = score.getMeasure(atMeasure(0, 0));
new Clef(ClefType.clefTreble);
clefs.add(c = ClefType.clefTreble);
new MeasureElementWrite(new Clef(c), measure, fr(0, 4)).execute();
keys.add(k = new TraditionalKey(1, Mode.Major));
new MeasureElementWrite(k, measure, fr(0, 4)).execute();
new VoiceElementWrite(measure.getVoice(0), atElement(0, 0, 0, 0), chord(pi(0, 1, 4), fr(1, 4)), null).execute();
clefs.add(c = ClefType.clefBass);
new MeasureElementWrite(new Clef(c), measure, fr(1, 4)).execute();
new VoiceElementWrite(measure.getVoice(0), atElement(0, 0, 0, 1), chord(pi(1, -1, 4), fr(1, 4)), null).execute();
clefs.add(c = ClefType.clefTreble);
new MeasureElementWrite(new Clef(c), measure, fr(2, 4)).execute();
keys.add(k = new TraditionalKey(-1, Mode.Major));
new MeasureElementWrite(k, measure, fr(2, 4)).execute();
new VoiceElementWrite(measure.getVoice(0), atElement(0, 0, 0, 2), chord(pi(0, 0, 4), fr(1, 4)), null).execute();
// measure 1
measure = score.getMeasure(atMeasure(0, 1));
new VoiceElementWrite(measure.getVoice(0), atElement(0, 1, 0, 0), chord(pi(0, 1, 4), fr(1, 4)), null).execute();
keys.add(k = new TraditionalKey(0, Mode.Major));
new MeasureElementWrite(k, measure, fr(1, 4)).execute();
clefs.add(c = ClefType.clefBass);
new MeasureElementWrite(new Clef(c), measure, fr(1, 4)).execute();
new VoiceElementWrite(measure.getVoice(0), atElement(0, 1, 0, 1), chord(pi(0, 0, 4), fr(2, 4)), null).execute();
return t3(score, clefs, keys);
}
use of com.xenoage.zong.core.music.clef.Clef in project Zong by Xenoage.
the class MeasureElementsSpacer method compute.
List<ElementSpacing> compute(BeatEList<Clef> clefs, @MaybeEmpty BeatEList<Key> keys, @MaybeNull TimeSignature time, boolean existsLeadingSpacing, List<VoiceSpacing> voiceSpacings, int staff, Notations notations, LayoutSettings layoutSettings) {
Key key0 = null;
if (keys.size() > 0 && keys.getFirst().beat.equals(_0))
key0 = keys.getFirst().element;
if (key0 == null && time == null && (clefs == null || clefs.size() == 0)) {
// nothing to do
return empty;
}
ArrayList<ElementSpacing> ret = alist();
float startOffset = layoutSettings.offsetMeasureStart;
// key and time
// ************
boolean isKey = !existsLeadingSpacing && key0 instanceof TraditionalKey;
boolean isTime = time != null;
if (isKey || isTime) {
float currentOffset = startOffset;
// ***
if (isKey) {
Notation keyNotation = notations.get(key0, staff);
ret.add(new SimpleSpacing(keyNotation, _0, startOffset));
currentOffset += keyNotation.getWidth().getUsedWidth();
}
// ****
if (time != null) {
Notation timeNotation = notations.get(time, staff);
ret.add(new SimpleSpacing(timeNotation, _0, currentOffset + timeNotation.getWidth().symbolWidth / 2));
currentOffset += timeNotation.getWidth().getUsedWidth();
}
// move voice elements, if not enough space before first voice element
ElementSpacing leftSE = getFirstElementSpacing(voiceSpacings);
if (leftSE != null) {
float leftSEx = getLeftX(leftSE);
// existing space
float ES = leftSEx;
// additional needed space
float AS = currentOffset - ES;
if (AS > 0) {
shift(voiceSpacings, AS);
startOffset += AS;
}
}
}
// voice 2: 1 o
if (clefs != null) {
for (BeatE<Clef> ME : clefs) {
Fraction MEb = ME.beat;
Notation MEnotation = notations.get(ME.element);
float MEwidth = MEnotation.getWidth().getWidth();
// if there is a leading spacing, ignore elements at beat 0
if (existsLeadingSpacing && !MEb.isGreater0())
continue;
// find VE1 and VE2 for the current element
ElementSpacing[] ses = getNearestSpacingElements(MEb, voiceSpacings);
ElementSpacing VE1 = ses[0], VE2 = ses[1];
// if VE1 is unknown, use startOffset. if VE2 is unknown, ignore this element
float VE1x = (VE1 != null ? getRightX(VE1) : startOffset);
if (VE2 == null)
continue;
float VE2x = getLeftX(VE2);
// existing space
float ES = VE2x - VE1x - 2 * layoutSettings.spacings.widthDistanceMin;
if (ES < MEwidth) {
// additional space needed
float AS = MEwidth - ES;
// move all elements at or after ME.beat
VE2x += AS;
shiftAfterBeat(voiceSpacings, AS, MEb);
}
// add measure element
float MEx = VE2x - layoutSettings.spacings.widthDistanceMin - MEwidth / 2;
ret.add(new SimpleSpacing(MEnotation, ME.beat, MEx));
}
}
ret.trimToSize();
return ret;
}
use of com.xenoage.zong.core.music.clef.Clef in project Zong by Xenoage.
the class LeadingSpacer method compute.
/**
* Computes the {@link LeadingSpacing} for the current measure.
*/
public LeadingSpacing compute(Context context, Notations notations) {
float xOffset = context.settings.offsetMeasureStart;
boolean useKey = false;
MusicContext musicContext = context.getMusicContext(At, null);
Key key = musicContext.getKey();
if (key instanceof TraditionalKey) {
useKey = true;
}
List<ElementSpacing> elements = alist(useKey ? 2 : 1);
// it is not the same element instance, but has the same meaning
Clef clef = new Clef(musicContext.getClef());
ClefNotation clefNotation = new ClefNotation(clef, new ElementWidth(0, context.settings.spacings.widthClef, 0), musicContext.getClef().getLp(), 1);
notations.add(clefNotation);
xOffset += context.settings.spacings.widthClef / 2;
elements.add(new SimpleSpacing(clefNotation, fr(0), xOffset));
xOffset += context.settings.spacings.widthClef / 2;
if (useKey) {
TraditionalKey tkey = (TraditionalKey) key;
xOffset += context.settings.spacings.widthDistanceMin;
// it is not the same element instance, but has the same meaning
TraditionalKey tradKey = new TraditionalKey(tkey.getFifths(), tkey.getMode());
TraditionalKeyNotation keyNotation = traditionalKeyNotator.compute(tradKey, context);
notations.add(keyNotation);
elements.add(new SimpleSpacing(keyNotation, fr(0), xOffset));
xOffset += keyNotation.getWidth().getWidth();
}
return new LeadingSpacing(elements, xOffset);
}
use of com.xenoage.zong.core.music.clef.Clef in project Zong by Xenoage.
the class ScoreReader method readToScore.
public void readToScore(Score score, ErrorHandling errorHandling) {
Context context = new Context(score, new ReaderSettings(errorHandling));
// create the measures of the parts
It<MxlPart> mxlParts = it(doc.getParts());
for (MxlPart mxlPart : mxlParts) {
// create measures
execute(new MeasureAddUpTo(score, mxlPart.getMeasures().size()));
// initialize each measure with a C clef
Part part = score.getStavesList().getParts().get(mxlParts.getIndex());
StavesRange stavesRange = score.getStavesList().getPartStaffIndices(part);
for (int staff : stavesRange.getRange()) {
execute(new MeasureElementWrite(new Clef(ClefType.clefTreble), score.getMeasure(MP.atMeasure(staff, 0)), _0));
}
}
// write a 4/4 measure and C key signature in the first measure
execute(new ColumnElementWrite(new TimeSignature(TimeType.time_4_4), score.getColumnHeader(0), _0, null));
execute(new ColumnElementWrite(new TraditionalKey(0), score.getColumnHeader(0), _0, null));
// read the parts
mxlParts = it(doc.getParts());
for (MxlPart mxlPart : mxlParts) {
// clear part-dependent context values
context.beginNewPart(mxlParts.getIndex());
// read the measures
It<MxlMeasure> mxlMeasures = it(mxlPart.getMeasures());
for (MxlMeasure mxlMeasure : mxlMeasures) {
try {
MeasureReader.readToContext(mxlMeasure, mxlMeasures.getIndex(), context);
} catch (MusicReaderException ex) {
throw new RuntimeException("Error at " + ex.getContext().toString(), ex);
} catch (Exception ex) {
throw new RuntimeException("Error (roughly) around " + context.toString(), ex);
}
}
}
// remove unclosed elements
context.removeUnclosedWedges();
// go through the whole score, and fill empty measures (that means, measures where
// voice 0 has no single VoiceElement) with rests
Fraction measureDuration = fr(1, 4);
for (int iStaff = 0; iStaff < score.getStavesCount(); iStaff++) {
Staff staff = score.getStaff(atStaff(iStaff));
for (int iMeasure : range(staff.getMeasures())) {
Measure measure = staff.getMeasure(iMeasure);
TimeSignature newTime = score.getHeader().getColumnHeader(iMeasure).getTime();
if (newTime != null) {
// time signature has changed
measureDuration = newTime.getType().getMeasureBeats();
}
if (measureDuration == null) {
// senza misura
// use whole rest
measureDuration = fr(4, 4);
}
Voice voice0 = measure.getVoice(0);
if (voice0.isEmpty()) {
// TODO: "whole rests" or split. currently, also 3/4 rests are possible
MP mp = atElement(iStaff, iMeasure, 0, 0);
new VoiceElementWrite(score.getVoice(mp), mp, new Rest(measureDuration), null).execute();
}
}
}
}
use of com.xenoage.zong.core.music.clef.Clef in project Zong by Xenoage.
the class ClefReader method read.
public Clef read() {
if (mxlClef == null)
return null;
ClefType clefType = readType();
Clef clef = (clefType != null ? new Clef(clefType) : null);
return clef;
}
Aggregations