package com.xenoage.zong.musiclayout.spacer.voice; import static com.xenoage.utils.collections.CollectionUtils.alist; import static com.xenoage.utils.math.Delta.DELTA_FLOAT; import static com.xenoage.utils.math.Fraction.fr; import static com.xenoage.zong.musiclayout.spacer.voice.SingleVoiceSpacer.singleVoiceSpacer; import static org.junit.Assert.assertEquals; import java.io.IOException; import org.junit.Before; import org.junit.Test; import com.xenoage.zong.core.music.Voice; import com.xenoage.zong.core.music.VoiceElement; import com.xenoage.zong.core.music.VoiceTest; import com.xenoage.zong.core.music.chord.Chord; import com.xenoage.zong.core.music.rest.Rest; import com.xenoage.zong.musiclayout.notation.ChordNotation; import com.xenoage.zong.musiclayout.notation.Notations; import com.xenoage.zong.musiclayout.notation.RestNotation; import com.xenoage.zong.musiclayout.settings.LayoutSettings; import com.xenoage.zong.musiclayout.settings.LayoutSettingsTest; import com.xenoage.zong.musiclayout.spacing.ElementSpacing; import com.xenoage.zong.musiclayout.spacing.ElementWidth; import com.xenoage.zong.musiclayout.spacing.VoiceSpacing; /** * Tests for {@link SingleVoiceSpacer}. * * @author Andreas Wenger */ public class SingleVoiceSpacerTest { private SingleVoiceSpacer testee = singleVoiceSpacer; private Rest r1, r2, r3, r4; private Chord g1, g2; private LayoutSettings layoutSettings; @Before public void setUp() throws IOException { r1 = new Rest(fr(1, 4)); r2 = new Rest(fr(1, 8)); r3 = new Rest(fr(1, 8)); r4 = new Rest(fr(1, 2)); g1 = VoiceTest.grace(1); g2 = VoiceTest.grace(1); layoutSettings = LayoutSettingsTest.loadTestSettings(); } /** * 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, 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(fr(0, 8), ses[0].beat); assertEquals(fr(2, 8), ses[1].beat); assertEquals(fr(3, 8), ses[2].beat); assertEquals(fr(4, 8), ses[3].beat); assertEquals(fr(8, 8), ses[4].beat); } /** * Computes a voice spacing with grace notes, * where the element before the grace notes has enough empty rear space * to take all the grace notes. * <pre> * Single elements: [-r1------------][g1][g2][--r4--] * Combined: --r1----~g1~g2~~~r4--- * </pre> (~: area used by two elements) */ @Test public void testGrace1() { //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, 13), 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, 300f, fr(4, 4), 5, notations, layoutSettings); //check spacing ElementSpacing[] ses = vs.elements.toArray(new ElementSpacing[0]);; float s = layoutSettings.offsetMeasureStart; assertEquals(5, ses.length); assertEquals(s + 2, ses[0].xIs, DELTA_FLOAT); assertEquals(s + 9, ses[1].xIs, DELTA_FLOAT); assertEquals(s + 12, ses[2].xIs, DELTA_FLOAT); assertEquals(s + 17, ses[3].xIs, DELTA_FLOAT); assertEquals(s + 22, ses[4].xIs, DELTA_FLOAT); //check beats assertEquals(fr(0, 8), ses[0].beat); assertEquals(fr(2, 8), ses[1].beat); assertEquals(fr(2, 8), ses[2].beat); assertEquals(fr(2, 8), ses[3].beat); assertEquals(fr(6, 8), ses[4].beat); } /** * 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, 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(fr(0, 8), ses[0].beat); assertEquals(fr(2, 8), ses[1].beat); assertEquals(fr(2, 8), ses[2].beat); assertEquals(fr(2, 8), ses[3].beat); assertEquals(fr(6, 8), ses[4].beat); } /** * Computes a voice spacing with grace notes, * where the element before the grace notes has not enough empty rear space * to take even a single 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 testGrace3() { //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, 3), 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, 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(fr(0, 8), ses[0].beat); assertEquals(fr(2, 8), ses[1].beat); assertEquals(fr(2, 8), ses[2].beat); assertEquals(fr(2, 8), ses[3].beat); assertEquals(fr(6, 8), ses[4].beat); } }