Skip to content

Commit

Permalink
Fix voice too long corruption
Browse files Browse the repository at this point in the history
  • Loading branch information
mathesoncalum committed Sep 30, 2024
1 parent 058263c commit 67156da
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 4 deletions.
28 changes: 28 additions & 0 deletions src/engraving/dom/noteentry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,34 @@ Ret Score::putNote(const Position& p, bool replace)

ChordRest* cr = m_is.cr();

// If there's an overlapping ChordRest at the current input position, shorten it...
if (!cr) {
MasterScore* ms = masterScore();
ChordRest* prevCr = m_is.segment()->nextChordRest(m_is.track(), /*backwards*/ true, /*stopAtMeasureBoundary*/ true);
if (prevCr && prevCr->endTick() > m_is.tick()) {
const Fraction overlapDuration = prevCr->endTick() - m_is.tick();
const Fraction desiredDuration = prevCr->ticks() - overlapDuration;

const InputState inputStateToRestore = m_is; // because changeCRlen will alter the input state
ms->changeCRlen(prevCr, desiredDuration, /*fillWithRest*/ false);

// Fill the difference with tied notes if necessary...
const Fraction difference = desiredDuration - prevCr->ticks();
if (prevCr->isChord() && difference.isNotZero()) {
Fraction startTick = prevCr->endTick();
Chord* prevChord = nullptr;
const std::vector<TDuration> durationList = toDurationList(difference, true);
for (const TDuration& dur : durationList) {
Chord* tieFrom = prevChord ? prevChord : toChord(prevCr);
prevChord = ms->addChord(startTick, dur, tieFrom, /*genTie*/ bool(tieFrom), tieFrom->tuplet());
startTick += dur.fraction();
}
}

m_is = inputStateToRestore;
}
}

auto checkTied = [&](){
if (!cr || !cr->isChord()) {
return false;
Expand Down
14 changes: 11 additions & 3 deletions src/engraving/dom/segment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -585,15 +585,23 @@ Segment* Segment::nextCR(track_idx_t track, bool sameStaff) const
// get the next ChordRest, start at this segment
//---------------------------------------------------------

ChordRest* Segment::nextChordRest(track_idx_t track, bool backwards) const
ChordRest* Segment::nextChordRest(track_idx_t track, bool backwards, bool stopAtMeasureBoundary) const
{
for (const Segment* seg = this; seg; seg = backwards ? seg->prev1() : seg->next1()) {
const Segment* seg = this;
while (seg) {
EngravingItem* el = seg->element(track);
if (el && el->isChordRest()) {
return toChordRest(el);
}

if (backwards) {
seg = stopAtMeasureBoundary ? seg->prev() : seg->prev1();
continue;
}

seg = stopAtMeasureBoundary ? seg->next() : seg->next1();
}
return 0;
return nullptr;
}

EngravingItem* Segment::element(track_idx_t track) const
Expand Down
2 changes: 1 addition & 1 deletion src/engraving/dom/segment.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ class Segment final : public EngravingItem

Segment* nextCR(track_idx_t track = muse::nidx, bool sameStaff = false) const;

ChordRest* nextChordRest(track_idx_t track, bool backwards = false) const;
ChordRest* nextChordRest(track_idx_t track, bool backwards = false, bool stopAtMeasureBoundary = false) const;

EngravingItem* element(track_idx_t track) const;

Expand Down

0 comments on commit 67156da

Please sign in to comment.