Search in sources :

Example 1 with ColumnSpacing

use of com.xenoage.zong.musiclayout.spacing.ColumnSpacing 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;
}
Also used : ChordNotation(com.xenoage.zong.musiclayout.notation.ChordNotation) ColumnSpacing(com.xenoage.zong.musiclayout.spacing.ColumnSpacing) SystemSpacing(com.xenoage.zong.musiclayout.spacing.SystemSpacing) ChordSpacing(com.xenoage.zong.musiclayout.spacing.ChordSpacing) MeasureSpacing(com.xenoage.zong.musiclayout.spacing.MeasureSpacing) BeatOffset(com.xenoage.zong.musiclayout.spacing.BeatOffset) VoiceSpacing(com.xenoage.zong.musiclayout.spacing.VoiceSpacing) ChordFactory.graceChord(com.xenoage.zong.core.music.chord.ChordFactory.graceChord) Chord(com.xenoage.zong.core.music.chord.Chord) Voice(com.xenoage.zong.core.music.Voice)

Example 2 with ColumnSpacing

use of com.xenoage.zong.musiclayout.spacing.ColumnSpacing in project Zong by Xenoage.

the class StretchMeasuresTest method computeSystemArrangementTestGrace.

/**
 * Checking if the elements are stretched correctly in a simple system
 * where there are grace notes. The space between grace notes and their following
 * full chord may not be stretched.
 */
@Test
public void computeSystemArrangementTestGrace() {
    // create an easy system for testing
    float offsetChord1 = 3;
    float offsetChord2 = 12;
    float offsetMeasureEnd = 16;
    float graceDistance = 2;
    SystemSpacing system = createSystemWith1MeasureGrace(offsetChord1, offsetChord2, offsetMeasureEnd, graceDistance);
    // stretch the system
    float newWidth = 28;
    testee.compute(system, newWidth);
    // compare the result
    ColumnSpacing newCol = system.columns.get(0);
    float stretch = (newWidth - +newCol.getLeadingWidthMm()) / offsetMeasureEnd;
    // beat offsets
    assertEquals(offsetChord1 * stretch, newCol.getBeatOffsets().get(0).getOffsetMm(), df);
    assertEquals(offsetChord2 * stretch, newCol.getBeatOffsets().get(1).getOffsetMm(), df);
    // element spacings
    VoiceSpacing newVoice = newCol.measures.get(0).voices.get(0);
    assertEquals(offsetChord1 * stretch, newVoice.elements.get(0).xIs, df);
    assertEquals(offsetChord2 * stretch - 2 * graceDistance, newVoice.elements.get(1).xIs, df);
    assertEquals(offsetChord2 * stretch - 1 * graceDistance, newVoice.elements.get(2).xIs, df);
    assertEquals(offsetChord2 * stretch, newVoice.elements.get(3).xIs, df);
}
Also used : ColumnSpacing(com.xenoage.zong.musiclayout.spacing.ColumnSpacing) SystemSpacing(com.xenoage.zong.musiclayout.spacing.SystemSpacing) VoiceSpacing(com.xenoage.zong.musiclayout.spacing.VoiceSpacing) Test(org.junit.Test)

Example 3 with ColumnSpacing

use of com.xenoage.zong.musiclayout.spacing.ColumnSpacing in project Zong by Xenoage.

the class StretchMeasuresTest method computeTest.

@Test
public void computeTest() {
    // create an easy system for testing
    float leadingWidth = 4;
    float offsetBeat1 = 3;
    float offsetBeat2 = 7;
    float offsetBeat3 = 12;
    SystemSpacing system = createSystemWith1Measure(leadingWidth, offsetBeat1, offsetBeat2, offsetBeat3);
    // stretch the system
    float newWidth = 20;
    testee.compute(system, newWidth);
    // compare the result
    // since the leading spacing (4 spaces) is not scaled, the
    // remaining 12 spaces of the voices width have to be scaled
    float stretch = (newWidth - leadingWidth) / offsetBeat3;
    ColumnSpacing newCol = system.columns.get(0);
    // beat offsets
    assertEquals(offsetBeat1 * stretch, newCol.getBeatOffsets().get(0).getOffsetMm(), df);
    assertEquals(offsetBeat2 * stretch, newCol.getBeatOffsets().get(1).getOffsetMm(), df);
    // element spacings
    VoiceSpacing newVoice = newCol.measures.get(0).voices.get(0);
    assertEquals(offsetBeat1 * stretch, newVoice.elements.get(0).xIs, df);
    assertEquals(offsetBeat2 * stretch, newVoice.elements.get(1).xIs, df);
}
Also used : ColumnSpacing(com.xenoage.zong.musiclayout.spacing.ColumnSpacing) SystemSpacing(com.xenoage.zong.musiclayout.spacing.SystemSpacing) VoiceSpacing(com.xenoage.zong.musiclayout.spacing.VoiceSpacing) Test(org.junit.Test)

Example 4 with ColumnSpacing

use of com.xenoage.zong.musiclayout.spacing.ColumnSpacing 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);
}
Also used : LeadingSpacing(com.xenoage.zong.musiclayout.spacing.LeadingSpacing) ColumnSpacing(com.xenoage.zong.musiclayout.spacing.ColumnSpacing) Fraction(com.xenoage.utils.math.Fraction) ElementSpacing(com.xenoage.zong.musiclayout.spacing.ElementSpacing) ColumnHeader(com.xenoage.zong.core.header.ColumnHeader) Column(com.xenoage.zong.core.music.util.Column) BarlinesBeatOffsetter(com.xenoage.zong.musiclayout.spacer.beat.BarlinesBeatOffsetter) MP.atMeasure(com.xenoage.zong.core.position.MP.atMeasure) Measure(com.xenoage.zong.core.music.Measure) MeasureSpacing(com.xenoage.zong.musiclayout.spacing.MeasureSpacing) VoiceSpacingsByStaff(com.xenoage.zong.musiclayout.layouter.columnspacing.VoiceSpacingsByStaff) BeatOffset(com.xenoage.zong.musiclayout.spacing.BeatOffset) ArrayList(java.util.ArrayList) List(java.util.List) VoiceSpacing(com.xenoage.zong.musiclayout.spacing.VoiceSpacing) Voice(com.xenoage.zong.core.music.Voice)

Example 5 with ColumnSpacing

use of com.xenoage.zong.musiclayout.spacing.ColumnSpacing in project Zong by Xenoage.

the class StretchMeasures method compute.

@Override
public void compute(SystemSpacing system, float usableWidthMm) {
    // compute width of all voice spacings
    // (leading spacings are not stretched)
    float voicesWidthMm = 0;
    float leadingsWidthMm = 0;
    for (ColumnSpacing column : system.columns) {
        voicesWidthMm += column.getVoicesWidthMm();
        leadingsWidthMm += column.getLeadingWidthMm();
    }
    // compute the stretching factor for the voice spacings
    if (voicesWidthMm == 0)
        return;
    float stretch = (usableWidthMm - leadingsWidthMm) / voicesWidthMm;
    // measure columns
    for (ColumnSpacing column : system.columns) {
        // beat offsets
        for (int i : range(column.beatOffsets)) {
            BeatOffset bo = column.beatOffsets.get(i);
            BeatOffset stretched = bo.withOffsetMm(bo.offsetMm * stretch);
            column.beatOffsets.set(i, stretched);
        }
        for (int i : range(column.barlineOffsets)) {
            BeatOffset bo = column.barlineOffsets.get(i);
            BeatOffset stretched = bo.withOffsetMm(bo.offsetMm * stretch);
            column.barlineOffsets.set(i, stretched);
        }
        // measures
        for (MeasureSpacing measure : column.measures) {
            // measure elements
            for (ElementSpacing element : measure.elements) {
                // stretch the offset
                element.xIs *= stretch;
            }
            // voices
            for (VoiceSpacing voice : measure.voices) {
                // traverse elements in reverse order, so we can align grace elements correctly
                // grace elements are not stretched, but the distance to their following full element
                // stays the same
                float lastElementOriginalOffsetIs = getLast(column.beatOffsets).offsetMm / voice.interlineSpace;
                for (int i : rangeReverse(voice.elements)) {
                    ElementSpacing element = voice.elements.get(i);
                    if (element.isGrace()) {
                        // grace element: keep distance to following element
                        float oldDistance = lastElementOriginalOffsetIs - element.xIs;
                        lastElementOriginalOffsetIs = element.xIs;
                        element.xIs = voice.elements.get(i + 1).xIs - oldDistance;
                    } else {
                        // normal element: stretch the offset
                        lastElementOriginalOffsetIs = element.xIs;
                        element.xIs *= stretch;
                    }
                }
            }
        }
    }
    // full system width
    system.widthMm = usableWidthMm;
    // columns have been changed
    system.onColumnsWidthChange();
}
Also used : ElementSpacing(com.xenoage.zong.musiclayout.spacing.ElementSpacing) ColumnSpacing(com.xenoage.zong.musiclayout.spacing.ColumnSpacing) MeasureSpacing(com.xenoage.zong.musiclayout.spacing.MeasureSpacing) BeatOffset(com.xenoage.zong.musiclayout.spacing.BeatOffset) VoiceSpacing(com.xenoage.zong.musiclayout.spacing.VoiceSpacing)

Aggregations

ColumnSpacing (com.xenoage.zong.musiclayout.spacing.ColumnSpacing)9 VoiceSpacing (com.xenoage.zong.musiclayout.spacing.VoiceSpacing)6 SystemSpacing (com.xenoage.zong.musiclayout.spacing.SystemSpacing)5 BeatOffset (com.xenoage.zong.musiclayout.spacing.BeatOffset)4 MeasureSpacing (com.xenoage.zong.musiclayout.spacing.MeasureSpacing)4 Voice (com.xenoage.zong.core.music.Voice)3 Chord (com.xenoage.zong.core.music.chord.Chord)2 ChordFactory.graceChord (com.xenoage.zong.core.music.chord.ChordFactory.graceChord)2 ChordNotation (com.xenoage.zong.musiclayout.notation.ChordNotation)2 ChordSpacing (com.xenoage.zong.musiclayout.spacing.ChordSpacing)2 ElementSpacing (com.xenoage.zong.musiclayout.spacing.ElementSpacing)2 Test (org.junit.Test)2 Fraction (com.xenoage.utils.math.Fraction)1 Score (com.xenoage.zong.core.Score)1 ScoreFormat (com.xenoage.zong.core.format.ScoreFormat)1 ColumnHeader (com.xenoage.zong.core.header.ColumnHeader)1 ScoreHeader (com.xenoage.zong.core.header.ScoreHeader)1 Measure (com.xenoage.zong.core.music.Measure)1 Beam (com.xenoage.zong.core.music.beam.Beam)1 Column (com.xenoage.zong.core.music.util.Column)1