use of com.xenoage.zong.core.music.Voice in project Zong by Xenoage.
the class VoicesBeatOffsetterTest method computeDistanceTest.
@Test
public void computeDistanceTest() {
Voice voice = createTestScore1Voice().getVoice(mp0);
List<ElementSpacing> spacings = createTestElementSpacings1Voice();
LinkedList<BeatOffset> emptyList = new LinkedList<>();
// distance: the offsets of the notes and rests are interesting,
// not the ones of the clefs, key signatures and time signatures,
// so the method has to use the last occurrence of a beat.
// distance between beat 0 and 4: must be 6
float distance = testee.computeMinimalDistance(Companion.fr(0), Companion.fr(4, 4), false, voice, spacings, emptyList, 1);
assertEquals(6, distance, Delta.DELTA_FLOAT);
// distance between beat 0 and 5: must be 0 (beat 5 isn't used)
distance = testee.computeMinimalDistance(Companion.fr(0), Companion.fr(5, 4), false, voice, spacings, emptyList, 1);
assertEquals(0, distance, Delta.DELTA_FLOAT);
// distance between beat 0 and 2: must be 2
distance = testee.computeMinimalDistance(Companion.fr(0), Companion.fr(2, 4), false, voice, spacings, emptyList, 1);
assertEquals(2, distance, Delta.DELTA_FLOAT);
// distance between beat 5 and 8: must be 0 (beat 5 isn't used)
distance = testee.computeMinimalDistance(Companion.fr(5), Companion.fr(8, 4), false, voice, spacings, emptyList, 1);
assertEquals(0, distance, Delta.DELTA_FLOAT);
}
use of com.xenoage.zong.core.music.Voice in project Zong by Xenoage.
the class StretchMeasuresTest method createSystemWith1Measure.
/**
* Creates and returns a simple {@link SystemSpacing} with only one
* measure with a clef and two notes, using the given parameters.
* @param leadingWidth width of the leading spacing in mm
* @param offsetBeat0 offset of beat 1/4 in mm
* @param offsetBeat1 offset of beat 3/4 in mm
* @param offsetBeat2 width of the voice spacing in mm
*/
public static SystemSpacing createSystemWith1Measure(float leadingWidth, float offsetBeat0, float offsetBeat1, float offsetBeat2) {
Chord chord1 = chord(Companion.pi(0, 0, 4), Companion.fr(2, 4));
Chord chord2 = chord(Companion.pi(1, 0, 4), Companion.fr(2, 4));
Voice voice = new Voice(alist(chord1, chord2));
List<BeatOffset> beatOffsets = alist(new BeatOffset(Companion.fr(1, 4), offsetBeat0), new BeatOffset(Companion.fr(3, 4), offsetBeat1), new BeatOffset(Companion.fr(5, 4), offsetBeat2));
float is = 1;
List<VoiceSpacing> voiceSpacings = alist(new VoiceSpacing(voice, is, alist(new ChordSpacing(new ChordNotation(chord1), beatOffsets.get(0).getBeat(), beatOffsets.get(0).getOffsetMm()), new ChordSpacing(new ChordNotation(chord2), beatOffsets.get(1).getBeat(), beatOffsets.get(1).getOffsetMm()))));
MeasureSpacing measureSpacing = new MeasureSpacing(atMeasure(0, 0), is, voiceSpacings, empty, LeadingSpacingMock.createGClefSpacing(leadingWidth));
List<MeasureSpacing> measureSpacings = alist(measureSpacing);
ColumnSpacing mcs = new ColumnSpacing(-1, measureSpacings, beatOffsets, alist(new BeatOffset(Companion.fr(0, 4), 0), new BeatOffset(Companion.fr(6, 4), offsetBeat2)));
SystemSpacing system = new SystemSpacing(ilist(mcs), 0, 0, leadingWidth + offsetBeat2, null, 0);
return system;
}
use of com.xenoage.zong.core.music.Voice in project Zong by Xenoage.
the class SingleVoiceSpacerTest method testGrace2.
/**
* Computes a voice spacing with grace notes,
* where the element before the grace notes has enough empty rear space
* to take at least one of the grace notes.
* <pre>
* Single elements: [-r1------][g1][g2][--r4--]
* Combined: --r1_~g1~g2~~~r4---
* </pre> (~: area used by two elements, _: minimal distance between elements)
*/
@Test
public void testGrace2() {
// create voice and notations
Voice voice = new Voice(alist((VoiceElement) r1, g1, g2, r4));
Notations notations = new Notations();
notations.add(new RestNotation(r1, new ElementWidth(2, 2, 7), null));
notations.add(new ChordNotation(g1, new ElementWidth(1, 2, 1)));
notations.add(new ChordNotation(g2, new ElementWidth(1, 2, 1)));
notations.add(new RestNotation(r4, new ElementWidth(3, 2, 3), null));
// compute spacing
VoiceSpacing vs = testee.compute(voice, 400f, Companion.fr(4, 4), 5, notations, layoutSettings);
// check spacing
ElementSpacing[] ses = vs.elements.toArray(new ElementSpacing[0]);
;
float s = layoutSettings.offsetMeasureStart;
float d = layoutSettings.spacings.widthDistanceMin;
assertEquals(5, ses.length);
assertEquals(s + 2, ses[0].xIs, DELTA_FLOAT);
assertEquals(s + 5 + d, ses[1].xIs, DELTA_FLOAT);
assertEquals(s + 8 + d, ses[2].xIs, DELTA_FLOAT);
assertEquals(s + 13 + d, ses[3].xIs, DELTA_FLOAT);
assertEquals(s + 18 + d, ses[4].xIs, DELTA_FLOAT);
// check beats
assertEquals(Companion.fr(0, 8), ses[0].beat);
assertEquals(Companion.fr(2, 8), ses[1].beat);
assertEquals(Companion.fr(2, 8), ses[2].beat);
assertEquals(Companion.fr(2, 8), ses[3].beat);
assertEquals(Companion.fr(6, 8), ses[4].beat);
}
use of com.xenoage.zong.core.music.Voice in project Zong by Xenoage.
the class SingleVoiceSpacerTest method testSimple.
/**
* Computes a simple voice spacing.
* <pre>
* Single elements: [-r1---][-r2-][-r3--][----r4--]
* Combined: --r1--~~r2_~-r3_~~---r4---
* </pre> (~: area used by two elements, _: minimal distance between elements)
*/
@Test
public void testSimple() {
// create voice and notations
Voice voice = new Voice(alist((VoiceElement) r1, r2, r3, r4));
Notations notations = new Notations();
notations.add(new RestNotation(r1, new ElementWidth(2, 2, 4), null));
notations.add(new RestNotation(r2, new ElementWidth(2, 2, 2), null));
notations.add(new RestNotation(r3, new ElementWidth(2, 2, 3), null));
notations.add(new RestNotation(r4, new ElementWidth(5, 2, 3), null));
// compute spacing
VoiceSpacing vs = testee.compute(voice, 200f, Companion.fr(4, 4), 5, notations, layoutSettings);
// check spacing
ElementSpacing[] ses = vs.elements.toArray(new ElementSpacing[0]);
float s = layoutSettings.offsetMeasureStart;
float d = layoutSettings.spacings.widthDistanceMin;
assertEquals(5, ses.length);
assertEquals(s + 2, ses[0].xIs, DELTA_FLOAT);
assertEquals(s + 8, ses[1].xIs, DELTA_FLOAT);
assertEquals(s + 12 + d, ses[2].xIs, DELTA_FLOAT);
assertEquals(s + 19 + 2 * d, ses[3].xIs, DELTA_FLOAT);
assertEquals(s + 24 + 2 * d, ses[4].xIs, DELTA_FLOAT);
// check beats
assertEquals(Companion.fr(0, 8), ses[0].beat);
assertEquals(Companion.fr(2, 8), ses[1].beat);
assertEquals(Companion.fr(3, 8), ses[2].beat);
assertEquals(Companion.fr(4, 8), ses[3].beat);
assertEquals(Companion.fr(8, 8), ses[4].beat);
}
use of com.xenoage.zong.core.music.Voice in project Zong by Xenoage.
the class ColumnSpacer method compute.
/**
* Computes a {@link ColumnSpacing} from a measure column.
* @param context the current context, with the current {@link MP} and precomputed
* element {@link Notation}s
* @param createLeading true, if a leading spacing has to be created, otherwise false
* @param notations the precomputed notations of the measure and voice elements
*/
public ColumnSpacing compute(Context context, boolean createLeading, Notations notations) {
context.saveMp();
int measureIndex = context.mp.measure;
Column column = context.score.getColumn(measureIndex);
ColumnHeader columnHeader = context.score.getHeader().getColumnHeader(measureIndex);
// compute the optimal spacings for each voice separately
List<List<VoiceSpacing>> voiceSpacingsByStaff = alist();
for (int iStaff : range(column)) {
List<VoiceSpacing> vss = alist();
Measure measure = column.get(iStaff);
for (Voice voice : measure.getVoices()) {
context.mp = MP.atVoice(iStaff, measureIndex, measure.getVoices().indexOf(voice));
VoiceSpacing vs = singleVoiceSpacer.compute(context, notations);
vss.add(vs);
}
voiceSpacingsByStaff.add(vss);
}
// compute the measure elements (like inner clefs) and accordingly updated voice spacings
ArrayList<List<ElementSpacing>> optimalMeasureElementsSpacingsByStaff = alist();
for (int iStaff : range(column)) {
context.mp = MP.atMeasure(iStaff, measureIndex);
List<ElementSpacing> measureSpacing = measureElementsSpacer.compute(context, createLeading, voiceSpacingsByStaff.get(iStaff), notations);
optimalMeasureElementsSpacingsByStaff.add(measureSpacing);
}
// compute the common beat offsets of this measure column
Fraction measureBeats = context.score.getMeasureBeats(measureIndex);
VoiceSpacingsByStaff voiceSpacings = new VoiceSpacingsByStaff(voiceSpacingsByStaff);
List<BeatOffset> beatOffsets = voicesBeatOffsetter.compute(voiceSpacings.getAll(), measureBeats, context.settings.offsetBeatsMinimal);
// recompute beat offsets with respect to barlines
BarlinesBeatOffsetter.Result offsets = barlinesBeatOffsetter.compute(beatOffsets, columnHeader, context.score.getMaxIS());
beatOffsets = offsets.voiceElementOffsets;
List<BeatOffset> barlineOffsets = offsets.barlineOffsets;
// compute the spacings for the whole column, so that equal beats are aligned
ArrayList<List<ElementSpacing>> alignedMeasureElementsSpacingsByStaff = alist();
for (int iStaff : range(column)) {
Measure measure = column.get(iStaff);
// voice spacings
for (int iVoice : range(measure.getVoices())) alignedVoicesSpacer.compute(voiceSpacings.get(iStaff, iVoice), beatOffsets);
// measure elements, based on the aligned voice spacings
context.mp = atMeasure(iStaff, measureIndex);
alignedMeasureElementsSpacingsByStaff.add(measureElementsSpacer.compute(context, createLeading, voiceSpacings.getStaff(iStaff), notations));
}
// compute spacings for each staff
List<MeasureSpacing> measureSpacings = alist(column.size());
for (int iStaff : range(column)) {
// create leading spacing, if needed
LeadingSpacing leadingSpacing = null;
if (createLeading) {
context.mp = atBeat(iStaff, measureIndex, 0, Fraction.Companion.get_0());
leadingSpacing = leadingSpacer.compute(context, notations);
}
// create measure spacing
float interlineSpace = context.score.getInterlineSpace(iStaff);
measureSpacings.add(new MeasureSpacing(atMeasure(iStaff, measureIndex), interlineSpace, voiceSpacings.getStaff(iStaff), alignedMeasureElementsSpacingsByStaff.get(iStaff), leadingSpacing));
}
context.restoreMp();
return new ColumnSpacing(measureIndex, measureSpacings, beatOffsets, barlineOffsets);
}
Aggregations