Skip to content

Commit

Permalink
beam beats in X/4 according to minimum durations
Browse files Browse the repository at this point in the history
  • Loading branch information
MarcSabatella committed Nov 15, 2014
1 parent d477e58 commit fef82c1
Show file tree
Hide file tree
Showing 15 changed files with 79 additions and 20 deletions.
3 changes: 2 additions & 1 deletion libmscore/beam.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1568,9 +1568,10 @@ void Beam::layout2(QList<ChordRest*>crl, SpannerSegmentType, int frag)
++i;
for (; i < n; ++i) {
ChordRest* c = crl[i];
ChordRest* p = i ? crl[i - 1] : 0;
int l = c->durationType().hooks() - 1;

Mode bm = Groups::endBeam(c);
Mode bm = Groups::endBeam(c, p);
bool b32 = (beamLevel >= 1) && (bm == Mode::BEGIN32);
bool b64 = (beamLevel >= 2) && (bm == Mode::BEGIN64);

Expand Down
20 changes: 18 additions & 2 deletions libmscore/groups.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ static std::vector<NoteGroup> noteGroups {
// endBeam
//---------------------------------------------------------

Beam::Mode Groups::endBeam(ChordRest* cr)
Beam::Mode Groups::endBeam(ChordRest* cr, ChordRest* prev)
{
if (cr->isGrace() || cr->beamMode() != Beam::Mode::AUTO)
return cr->beamMode();
Expand All @@ -76,7 +76,23 @@ Beam::Mode Groups::endBeam(ChordRest* cr)
const Groups& g = cr->staff()->group(cr->tick());
Fraction stretch = cr->staff()->timeStretch(cr->tick());
int tick = (cr->rtick() * stretch.numerator()) / stretch.denominator();
return g.beamMode(tick, d.type());
Beam::Mode val = g.beamMode(tick, d.type());

// context-dependent checks
if (val == Beam::Mode::AUTO && tick) {
// if current or previous cr is in tuplet (but not both in same tuplet):
// consider it as if this were next shorter duration
if (prev && (cr->tuplet() != prev->tuplet()) && (d == prev->durationType())) {
if (d >= TDuration::DurationType::V_EIGHTH)
val = g.beamMode(tick, TDuration::DurationType::V_16TH);
else if (d == TDuration::DurationType::V_16TH)
val = g.beamMode(tick, TDuration::DurationType::V_32ND);
else
val = g.beamMode(tick, TDuration::DurationType::V_64TH);
}
}

return val;
}

//---------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion libmscore/groups.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class Groups : public std::vector<GroupNode> {
void dump(const char*) const;

static const Groups& endings(const Fraction& f);
static Beam::Mode endBeam(ChordRest* cr);
static Beam::Mode endBeam(ChordRest* cr, ChordRest* prev = 0);
};


Expand Down
70 changes: 56 additions & 14 deletions libmscore/layout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1162,34 +1162,76 @@ void Score::layoutStage2()
Beam* beam = 0; // current beam
Measure* measure = 0;

Beam::Mode bm = Beam::Mode::AUTO;
Beam::Mode bm = Beam::Mode::AUTO;
Segment::Type st = Segment::Type::ChordRest;
ChordRest* prev = 0;
ChordRest* prev = 0;
bool checkBeats = false;
Fraction stretch = 1;
QHash<int, TDuration> beatSubdivision;

for (Segment* segment = firstSegment(st); segment; segment = segment->next1(st)) {
ChordRest* cr = static_cast<ChordRest*>(segment->element(track));
if (cr == 0)
continue;

// handle grace notes and cross-measure beaming
if (cr->type() == Element::Type::CHORD) {
Chord* chord = static_cast<Chord*>(cr);
beamGraceNotes(chord, false); // grace before
beamGraceNotes(chord, true); // grace after
beamGraceNotes(chord, false); // grace before
beamGraceNotes(chord, true); // grace after
// set up for cross-measure values as soon as possible
// to have all computations (stems, hooks, ...) consistent with it
if (!chord->isGrace())
chord->crossMeasureSetup(crossMeasure);
}

bm = Groups::endBeam(cr);
// if this is a new measure, and it's simple meter (actually X/4),
// then perform a prepass to determine the subdivision of each beat
if (segment->measure() != measure) {
Measure* m = segment->measure();
TimeSig* ts = cr->staff()->timeSig(m->tick());
beatSubdivision.clear();
checkBeats = false;
stretch = ts ? ts->stretch() : 1;
if (ts && ts->denominator() == 4) {
checkBeats = true;
for (Segment* s = m->first(st); s; s = s->next(st)) {
ChordRest* mcr = static_cast<ChordRest*>(s->element(track));
if (mcr == 0)
continue;
int beat = ((mcr->rtick() * stretch.numerator()) / stretch.denominator()) / MScore::division;
if (beatSubdivision.contains(beat))
beatSubdivision[beat] = qMin(beatSubdivision[beat], mcr->durationType());
else
beatSubdivision[beat] = mcr->durationType();
}
}
}

// get defaults from time signature properties
bm = Groups::endBeam(cr, prev);

// perform additional context-dependent checks
if (bm == Beam::Mode::AUTO) {

// check if we need to break beams according to minimum duration in current / previous beat
if (checkBeats && cr->rtick()) {
int tick = (cr->rtick() * stretch.numerator()) / stretch.denominator();
// check if on the beat
if (tick % MScore::division == 0) {
int beat = tick / MScore::division;
// get minimum duration for this & previous beat
TDuration minDuration = qMin(beatSubdivision[beat], beatSubdivision[beat - 1]);
// re-calculate beam as if this were the duration of current chordrest
TDuration saveDuration = cr->durationType();
cr->setDurationType(minDuration);
bm = Groups::endBeam(cr, prev);
cr->setDurationType(saveDuration);
}
}

}

// end beam at new tuplet or end tuplet, if the next/prev duration type is different
if (cr->tuplet()
&& !cr->tuplet()->elements().isEmpty()
&& cr->tuplet()->elements().front() == cr
&& prev && prev->durationType() == cr->durationType())
bm = Beam::Mode::BEGIN;
else if (prev && prev->tuplet() && !prev->tuplet()->elements().isEmpty()
&& prev->tuplet()->elements().last() == prev && prev->durationType() == cr->durationType())
bm = Beam::Mode::BEGIN;
prev = cr;

// if chord has hooks and is 2nd element of a cross-measure value
Expand Down
Binary file modified vtest/beams-3-ref.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added vtest/beams-4-ref.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added vtest/beams-4.mscz
Binary file not shown.
Binary file added vtest/beams-5-ref.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added vtest/beams-5.mscz
Binary file not shown.
Binary file added vtest/beams-6-ref.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added vtest/beams-6.mscz
Binary file not shown.
Binary file added vtest/beams-7-ref.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added vtest/beams-7.mscz
Binary file not shown.
2 changes: 1 addition & 1 deletion vtest/gen
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ else
accidental-1 accidental-2 accidental-3 accidental-4 accidental-5\
accidental-6 accidental-7 accidental-8 accidental-9\
tie-1 tie-2 tie-3 grace-1 grace-2 grace-3 harmony-1 harmony-2 harmony-3 harmony-4\
beams-1 beams-2 beams-3\
beams-1 beams-2 beams-3 beams-4 beams-5 beams-6 beams-7\
user-offset-1 user-offset-2 chord-space-1 tablature-1 image-1\
lyrics-1 lyrics-2 lyrics-3 voice-1"
fi
Expand Down
2 changes: 1 addition & 1 deletion vtest/gen.bat
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ set SRC=mmrest-1,bravura-mmrest,gonville-mmrest,mmrest-2,mmrest-4,mmrest-5,mmres
accidental-1,accidental-2,accidental-3,accidental-4,accidental-5, ^
accidental-6,accidental-7,accidental-8,accidental-9, ^
tie-1,tie-2,tie-3,grace-1,grace-2,grace-3,harmony-1,harmony-2,harmony-3,harmony-4, ^
beams-1,beams-2,beams-3, ^
beams-1,beams-2,beams-3,beams-4,beams-5,beams-6,beams-7, ^
user-offset-1,user-offset-2,chord-space-1,tablature-1,image-1, ^
lyrics-1,lyrics-2,lyrics-3,voice-1

Expand Down

0 comments on commit fef82c1

Please sign in to comment.