Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
vpereverzev committed Oct 14, 2022
1 parent fb19f0f commit 0995057
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 13 deletions.
44 changes: 40 additions & 4 deletions src/engraving/libmscore/spannermap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

#include "spannermap.h"
#include "spanner.h"
#include "part.h"

#include "log.h"

Expand All @@ -45,10 +46,7 @@ SpannerMap::SpannerMap()

void SpannerMap::update() const
{
std::vector<interval_tree::Interval<Spanner*> > intervals;
for (auto i : *this) {
intervals.push_back(interval_tree::Interval<Spanner*>(i.second->tick().ticks(), i.second->tick2().ticks(), i.second));
}
IntervalList intervals = collectIntervals();
tree = interval_tree::IntervalTree<Spanner*>(intervals);
dirty = false;
}
Expand Down Expand Up @@ -81,6 +79,44 @@ const std::vector<interval_tree::Interval<Spanner*> >& SpannerMap::findOverlappi
return results;
}

SpannerMap::IntervalList SpannerMap::collectIntervals() const
{
using IntervalsByPart = std::map<ID, IntervalList>;

IntervalsByPart intervalsByPart;

//!Note Because of the current UX of spanners adjustments spanners collision is a regular thing,
//! so we have to manage those cases when two similar spanners (e.g. Pedal line) are overlapping
//! with each other.
constexpr int collidingSpannersPadding = 1;

for (const auto& pair : *this) {
IntervalList& intervalList = intervalsByPart[pair.second->part()->id()];

int newSpannerStartTick = pair.second->tick().ticks();
int newSpannerEndTick = pair.second->tick2().ticks();

if (!intervalList.empty()) {
auto lastIntervalIt = intervalList.rbegin();
if (lastIntervalIt->stop >= newSpannerStartTick) {
lastIntervalIt->stop = newSpannerStartTick - collidingSpannersPadding;
}
}

intervalList.emplace_back(interval_tree::Interval<Spanner*>(newSpannerStartTick,
newSpannerEndTick,
pair.second));
}

IntervalList result;

for (const auto& pair : intervalsByPart) {
result.insert(result.end(), pair.second.begin(), pair.second.end());
}

return result;
}

//---------------------------------------------------------
// addSpanner
//---------------------------------------------------------
Expand Down
5 changes: 5 additions & 0 deletions src/engraving/libmscore/spannermap.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,16 @@ class SpannerMap : std::multimap<int, Spanner*>
typedef typename std::multimap<int, Spanner*>::const_reverse_iterator const_reverse_it;
typedef typename std::multimap<int, Spanner*>::const_iterator const_it;

using IntervalList = std::vector<interval_tree::Interval<Spanner *> >;

SpannerMap();

const std::vector<interval_tree::Interval<Spanner*> >& findContained(int start, int stop) const;
const std::vector<interval_tree::Interval<Spanner*> >& findOverlapping(int start, int stop) const;
const std::multimap<int, Spanner*>& map() const { return *this; }

IntervalList collectIntervals() const;

const_reverse_it crbegin() const { return std::multimap<int, Spanner*>::crbegin(); }
const_reverse_it crend() const { return std::multimap<int, Spanner*>::crend(); }
const_it cbegin() const { return std::multimap<int, Spanner*>::cbegin(); }
Expand Down
22 changes: 14 additions & 8 deletions src/engraving/playback/metaparsers/internal/spannersmetaparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@
#include "libmscore/note.h"
#include "libmscore/spanner.h"
#include "libmscore/trill.h"
#include "libmscore/pedal.h"

#include "playback/utils/pitchutils.h"

using namespace mu::engraving;

void SpannersMetaParser::doParse(const EngravingItem* item, const RenderingContext& ctx, mpe::ArticulationMap& result)
void SpannersMetaParser::doParse(const EngravingItem* item, const RenderingContext& spannerCtx, mpe::ArticulationMap& result)
{
IF_ASSERT_FAILED(item->isSpanner()) {
return;
Expand All @@ -43,7 +44,7 @@ void SpannersMetaParser::doParse(const EngravingItem* item, const RenderingConte

mpe::pitch_level_t overallPitchRange = 0;
mpe::dynamic_level_t overallDynamicRange = 0;
int overallDurationTicks = spanner->ticks().ticks();
int overallDurationTicks = spannerCtx.nominalDurationTicks;

switch (spanner->type()) {
case ElementType::SLUR: {
Expand All @@ -64,8 +65,13 @@ void SpannersMetaParser::doParse(const EngravingItem* item, const RenderingConte

break;
}
case ElementType::PEDAL:
type = mpe::ArticulationType::Pedal;
case ElementType::PEDAL: {
type = mpe::ArticulationType::Pedal;
const Pedal* pedal = toPedal(spanner);
if (pedal->endHookType() == HookType::HOOK_45) {
overallDurationTicks -= Constants::division / 4;
}
}
break;
case ElementType::LET_RING:
type = mpe::ArticulationType::LaissezVibrer;
Expand All @@ -90,7 +96,7 @@ void SpannersMetaParser::doParse(const EngravingItem* item, const RenderingConte
} else if (trill->trillType() == TrillType::PRALLPRALL_LINE) {
type = mpe::ArticulationType::LinePrall;
}
overallDurationTicks = ctx.nominalDurationTicks;
overallDurationTicks = spannerCtx.nominalDurationTicks;
break;
}
case ElementType::GLISSANDO: {
Expand Down Expand Up @@ -135,11 +141,11 @@ void SpannersMetaParser::doParse(const EngravingItem* item, const RenderingConte

mpe::ArticulationMeta articulationMeta;
articulationMeta.type = type;
articulationMeta.pattern = ctx.profile->pattern(type);
articulationMeta.timestamp = ctx.nominalTimestamp;
articulationMeta.pattern = spannerCtx.profile->pattern(type);
articulationMeta.timestamp = spannerCtx.nominalTimestamp;
articulationMeta.overallPitchChangesRange = overallPitchRange;
articulationMeta.overallDynamicChangesRange = overallDynamicRange;
articulationMeta.overallDuration = durationFromTicks(ctx.beatsPerSecond.val, overallDurationTicks);
articulationMeta.overallDuration = durationFromTicks(spannerCtx.beatsPerSecond.val, overallDurationTicks);

appendArticulationData(std::move(articulationMeta), result);
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class SpannersMetaParser : public MetaParserBase<SpannersMetaParser>
protected:
friend MetaParserBase;

static void doParse(const EngravingItem* item, const RenderingContext& ctx, mpe::ArticulationMap& result);
static void doParse(const EngravingItem* item, const RenderingContext& spannerCtx, mpe::ArticulationMap& result);
};
}

Expand Down

0 comments on commit 0995057

Please sign in to comment.