Search in sources :

Example 1 with Fragments

use of com.xenoage.zong.musiclayout.notation.beam.Fragments in project Zong by Xenoage.

the class BeamFragmenter method compute.

/**
 * Computes the line fragments for all lines of the given beam,
 * starting with the 16th, then 32nd, ... line.
 */
public List<Fragments> compute(Beam beam) {
    int linesCount = beam.getMaxLinesCount();
    List<Fragments> ret = alist(linesCount - 1);
    Fragments lastFragments = null;
    for (int line : range(1, linesCount - 1)) ret.add(lastFragments = compute(beam, line, lastFragments));
    return ret;
}
Also used : Fragments(com.xenoage.zong.musiclayout.notation.beam.Fragments)

Example 2 with Fragments

use of com.xenoage.zong.musiclayout.notation.beam.Fragments in project Zong by Xenoage.

the class BeamStamper method stamp.

/**
 * Computes the stampings for the given beam and returns them.
 * @param beam    the beam to stamp
 * @param staff   the staff stamping of the first chord of the beam
 */
public List<BeamStamping> stamp(BeamSpacing beam, StaffStamping staff) {
    int beamSize = beam.chords.size();
    val leftEndSp = beam.getLeftSp();
    val rightEndSp = beam.getRightSp();
    val primaryStemDir = beam.getStemDirection(0);
    // number of beam lines
    int linesCount = beam.notation.getLinesCount();
    // first guess of the size (is correct for simple beams)
    List<BeamStamping> ret = alist(linesCount);
    // first line (8th line) is always continuous
    val beam8th = new BeamStamping(beam, staff, leftEndSp, rightEndSp, primaryStemDir);
    ret.add(beam8th);
    // this is stored in the notation
    for (int i : range(beam.notation.linesFragments)) {
        int line = i + 1;
        float lineLp = -1 * primaryStemDir.getSign() * (lineHeightIs + beam.notation.gapIs) * 2 * line;
        val beamLinePoints = new LinearInterpolationPoints(leftEndSp.lp + lineLp, rightEndSp.lp + lineLp, leftEndSp.xMm, rightEndSp.xMm);
        // create the line stampings
        float startXMm = 0;
        Fragments fragments = beam.notation.linesFragments.get(i);
        for (int iChord : range(fragments)) {
            Fragment fragment = fragments.get(iChord);
            float stemXMm = beam.getStemEndSp(iChord).xMm;
            if (fragment == Start) {
                // begin a new beam line
                startXMm = stemXMm;
            } else if (fragment == Stop) {
                // end the beam line and stem it
                float stopXMm = stemXMm;
                SP leftSp = sp(startXMm, INSTANCE.interpolateLinear(beamLinePoints, startXMm));
                SP rightSp = sp(stopXMm, INSTANCE.interpolateLinear(beamLinePoints, stopXMm));
                val stamping = new BeamStamping(beam, staff, leftSp, rightSp, primaryStemDir);
                ret.add(stamping);
            } else if (fragment == HookLeft || fragment == HookRight) {
                // left or right hook
                float lengthMm = hookLengthIs * staff.is;
                float x1Mm = (fragment == HookLeft ? stemXMm - lengthMm : stemXMm);
                float x2Mm = (fragment == HookLeft ? stemXMm : stemXMm + lengthMm);
                SP leftSp = sp(x1Mm, INSTANCE.interpolateLinear(beamLinePoints, x1Mm));
                SP rightSp = sp(x2Mm, INSTANCE.interpolateLinear(beamLinePoints, x2Mm));
                val stamping = new BeamStamping(beam, staff, leftSp, rightSp, primaryStemDir);
                ret.add(stamping);
            }
        }
    }
    return ret;
}
Also used : lombok.val(lombok.val) BeamStamping(com.xenoage.zong.musiclayout.stampings.BeamStamping) Fragments(com.xenoage.zong.musiclayout.notation.beam.Fragments) LinearInterpolationPoints(com.xenoage.utils.math.MathUtils.LinearInterpolationPoints) Fragment(com.xenoage.zong.musiclayout.notation.beam.Fragment) SP(com.xenoage.zong.core.music.format.SP)

Example 3 with Fragments

use of com.xenoage.zong.musiclayout.notation.beam.Fragments in project Zong by Xenoage.

the class BeamFragmenterTest method computeTest.

@Test
public void computeTest() {
    ChlapikBeamFragments source = new ChlapikBeamFragments();
    Beam b;
    // example of row 1, column 1
    b = source.exampleRow1Col1();
    try {
        // not working for 8th lines
        testee.compute(b, 0, null);
        fail();
    } catch (IllegalArgumentException ex) {
    // ok
    }
    Fragments wp = testee.compute(b, 2, null);
    // 32th
    assertEqualsList(wp, None, None, None);
    // 16th
    assertEqualsList(testee.compute(b, 1, wp), HookRight, None, HookLeft);
    // example of row 1, column 2
    b = source.exampleRow1Col2();
    // 16th
    assertEqualsList(testee.compute(b, 1, null), HookRight, None, HookLeft);
    // example of row 1, column 3
    b = source.exampleRow1Col3();
    // 16th
    assertEqualsList(testee.compute(b, 1, null), HookRight, None, None, HookLeft);
    // example of row 1, column 4
    b = source.exampleRow1Col4();
    // 16th
    assertEqualsList(testee.compute(b, 1, null), HookRight, None, None, HookLeft);
    // example of row 2, column 1
    b = source.exampleRow2Col1();
    // 16th
    assertEqualsList(testee.compute(b, 1, null), None, HookLeft);
    // example of row 2, column 2
    b = source.exampleRow2Col2();
    // 16th
    assertEqualsList(testee.compute(b, 1, null), None, HookLeft);
    // example of row 2, column 3
    b = source.exampleRow2Col3();
    wp = testee.compute(b, 2, null);
    // 32th
    assertEqualsList(wp, None, HookLeft, None, HookLeft);
    // 16th
    assertEqualsList(testee.compute(b, 1, wp), Start, None, None, Stop);
    // example of row 2, column 4
    b = source.exampleRow2Col4();
    wp = testee.compute(b, 2, null);
    // 32th
    assertEqualsList(wp, None, HookLeft, None, HookLeft);
    // 16th
    assertEqualsList(testee.compute(b, 1, wp), Start, None, None, Stop);
    // example of row 3, column 2
    b = source.exampleRow3Col2();
    // 16th
    assertEqualsList(testee.compute(b, 1, null), HookRight, None, HookLeft, None);
    // example of row 3, column 4
    b = source.exampleRow3Col4();
    // 16th
    assertEqualsList(testee.compute(b, 1, null), None, HookRight, None);
    // example of row 3, column 6
    b = source.exampleRow3Col6();
    wp = testee.compute(b, 2, null);
    // 32th
    assertEqualsList(wp, None, HookLeft, None, HookLeft);
    // 16th
    assertEqualsList(testee.compute(b, 1, wp), None, HookLeft, Start, Stop);
}
Also used : Beam(com.xenoage.zong.core.music.beam.Beam) ChlapikBeamFragments(material.beam.fragments.ChlapikBeamFragments) Fragments(com.xenoage.zong.musiclayout.notation.beam.Fragments) ChlapikBeamFragments(material.beam.fragments.ChlapikBeamFragments) Test(org.junit.Test)

Example 4 with Fragments

use of com.xenoage.zong.musiclayout.notation.beam.Fragments in project Zong by Xenoage.

the class BeamFragmenter method compute.

/**
 * Computes the fragments for the given line (1: 16th line, 2: 32th line, ...).
 * Use an algorithm based on the rules in Chlapik, page 45, rule 6.
 *
 * Begin with the highest line (e.g. 32th before 16th), and use the result of line n
 * as a parameter to compute line n-1 (for the first computation, use null).
 * This is needed to support Chlapik, page 45, rule 6, example of row 3, column 6.
 * Without that, the 16th line would go from the second note to the fourth one.
 */
Fragments compute(Beam beam, int line, Fragments higherLine) {
    if (line < 1)
        throw new IllegalArgumentException("This method only works for 16th lines or higher");
    // in this algorithm, we go from note to note, looking for "groups".
    // groups are consecutive chords/stems with the same number of flags (or
    // a higher number inbetween) and not divided by a subdivision break.
    // initialize return array with none-waypoints
    Fragments ret = new Fragments(beam.size());
    int lastFlagsCount = -1;
    // start chord of the last group, or -1 if no group is open
    int startChord = -1;
    // stop chord of the last group, or -1 if group is open
    int stopChord = -1;
    for (int iChord : range(beam.size() + 1)) {
        if (iChord < beam.getWaypoints().size()) {
            // another chord within the beam
            Chord chord = beam.getChord(iChord);
            int flagsCount = INSTANCE.getFlagsCount(chord.getDuration());
            // enough flags for the given line? (e.g. a 8th beam has no 16th line)
            if (flagsCount >= line + 1) {
                // yes, we need a line of the given line for this stem
                if (startChord == -1) {
                    if (higherLine == null || higherLine.get(iChord) != HookLeft) {
                        // start new group
                        startChord = iChord;
                        lastFlagsCount = flagsCount;
                    } else {
                        // example mentioned in the method documentation (Chlapik, page 45, row 3, col 6)
                        // we place a hook. this is not explicitly mentioned in the text, but seems to
                        // be right when looking at the example.
                        startChord = iChord;
                        stopChord = iChord;
                    }
                } else if (lastFlagsCount > -1 && (// less flags than previous stem
                flagsCount < flagsCount || beam.isEndOfSubdivision(iChord))) {
                    // forced subdivision break
                    // end the group here
                    stopChord = iChord - 1;
                }
            } else {
                // no, we need no line of the given line for this stem
                // so, close the last group
                stopChord = iChord - 1;
            }
        } else {
            // no more chord in the beam, so we have to close
            stopChord = iChord - 1;
        }
        // if a group was closed, create it
        if (startChord > -1 && stopChord > -1) {
            // type of line is dependent on number of chords in the group
            int chordsCount = stopChord - startChord + 1;
            if (chordsCount > 1) {
                // simple case: more than one chord. create a normal line
                // between those stems
                ret.set(startChord, Start);
                ret.set(stopChord, Stop);
            } else {
                // more difficult case: exactly one chord.
                if (startChord == 0) {
                    // first chord in beam has always hook to the right
                    ret.set(startChord, HookRight);
                } else if (startChord == beam.getWaypoints().size() - 1) {
                    // last chord in beam has always hook to the left
                    ret.set(startChord, HookLeft);
                } else {
                    // middle chords have left hook, if the preceding chord
                    // has a longer or equal duration than the following chord,
                    // otherwise they have a right hook
                    Fraction left = beam.getChord(startChord - 1).getDuration();
                    Fraction right = beam.getChord(startChord + 1).getDuration();
                    if (left.compareTo(right) >= 0)
                        ret.set(startChord, HookLeft);
                    else
                        ret.set(startChord, HookRight);
                }
            }
            // reset group data
            startChord = -1;
            stopChord = -1;
            lastFlagsCount = -1;
        }
    }
    return ret;
}
Also used : Fragments(com.xenoage.zong.musiclayout.notation.beam.Fragments) Fraction(com.xenoage.utils.math.Fraction) Chord(com.xenoage.zong.core.music.chord.Chord)

Example 5 with Fragments

use of com.xenoage.zong.musiclayout.notation.beam.Fragments in project Zong by Xenoage.

the class BeamNotator method compute.

@MaybeNull
public BeamNotation compute(Beam beam, Notations notations) {
    // compute fragments
    List<Fragments> fragments = beamFragmenter.compute(beam);
    // get minimum stem length and gap
    BeamRules beamRules = BeamRules.getRules(beam);
    float gapIs = beamRules.getGapIs();
    // collect chords
    List<ChordNotation> chords = notations.getBeamChords(beam);
    // create notation
    BeamNotation beamNotation = new BeamNotation(beam, beam.getMP(), fragments, gapIs, chords);
    return beamNotation;
}
Also used : ChordNotation(com.xenoage.zong.musiclayout.notation.ChordNotation) Fragments(com.xenoage.zong.musiclayout.notation.beam.Fragments) BeamRules(com.xenoage.zong.musiclayout.notator.beam.lines.BeamRules) BeamNotation(com.xenoage.zong.musiclayout.notation.BeamNotation) MaybeNull(com.xenoage.utils.annotations.MaybeNull)

Aggregations

Fragments (com.xenoage.zong.musiclayout.notation.beam.Fragments)5 MaybeNull (com.xenoage.utils.annotations.MaybeNull)1 Fraction (com.xenoage.utils.math.Fraction)1 LinearInterpolationPoints (com.xenoage.utils.math.MathUtils.LinearInterpolationPoints)1 Beam (com.xenoage.zong.core.music.beam.Beam)1 Chord (com.xenoage.zong.core.music.chord.Chord)1 SP (com.xenoage.zong.core.music.format.SP)1 BeamNotation (com.xenoage.zong.musiclayout.notation.BeamNotation)1 ChordNotation (com.xenoage.zong.musiclayout.notation.ChordNotation)1 Fragment (com.xenoage.zong.musiclayout.notation.beam.Fragment)1 BeamRules (com.xenoage.zong.musiclayout.notator.beam.lines.BeamRules)1 BeamStamping (com.xenoage.zong.musiclayout.stampings.BeamStamping)1 lombok.val (lombok.val)1 ChlapikBeamFragments (material.beam.fragments.ChlapikBeamFragments)1 Test (org.junit.Test)1