Skip to content

Commit e23dec3

Browse files
Merge pull request #31291 from RomanPudashkin/online_sounds_repeated_lyrics_playback
[4.6.4] Online sounds: fix repeated lyrics playback
2 parents 9efcae1 + 9d2f8d8 commit e23dec3

5 files changed

Lines changed: 106 additions & 20 deletions

File tree

src/engraving/playback/playbackcontext.cpp

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ void PlaybackContext::update(const ID partId, const Score* score, bool expandRep
326326
for (const Segment* segment = measure->first(); segment; segment = segment->next()) {
327327
int segmentStartTick = segment->tick().ticks() + tickPositionOffset;
328328

329-
handleSegmentElements(segment, segmentStartTick, measureRepeats);
329+
handleSegmentElements(repeatSegment, segment, segmentStartTick, measureRepeats);
330330
handleSegmentAnnotations(partId, segment, segmentStartTick);
331331
}
332332
}
@@ -354,6 +354,7 @@ void PlaybackContext::clear()
354354
m_textArticulationsByTrack.clear();
355355
m_syllablesByTrack.clear();
356356
m_currentVerseNumByChordRest.clear();
357+
m_multiVerseLyricsPositionMap.clear();
357358
}
358359

359360
bool PlaybackContext::hasSoundFlags() const
@@ -680,7 +681,8 @@ void PlaybackContext::handleSegmentAnnotations(const ID partId, const Segment* s
680681
}
681682
}
682683

683-
void PlaybackContext::handleSegmentElements(const Segment* segment, const int segmentPositionTick,
684+
void PlaybackContext::handleSegmentElements(const RepeatSegment* repeat, const Segment* segment,
685+
const int segmentPositionTick,
684686
std::vector<const MeasureRepeat*>& foundMeasureRepeats)
685687
{
686688
for (track_idx_t track = m_partStartTrack; track < m_partEndTrack; ++track) {
@@ -698,22 +700,26 @@ void PlaybackContext::handleSegmentElements(const Segment* segment, const int se
698700
m_usedVoices.insert(item->voice());
699701

700702
const ChordRest* chordRest = toChordRest(item);
701-
const std::vector<Lyrics*>& lyricsList = chordRest->lyrics();
702-
if (lyricsList.empty()) {
703+
if (chordRest->lyrics().empty()) {
703704
continue;
704705
}
705706

706-
int verseNum = 0;
707+
const Lyrics* lyrics = nullptr;
707708

708709
auto verseNumIt = m_currentVerseNumByChordRest.find(chordRest);
709710
if (verseNumIt == m_currentVerseNumByChordRest.end()) {
710711
m_currentVerseNumByChordRest[chordRest] = 0;
712+
lyrics = chordRest->lyrics(0);
713+
if (chordRest->lyrics().size() > 1) {
714+
m_multiVerseLyricsPositionMap[track].insert(chordRest->tick().ticks());
715+
}
716+
} else if (hasOnlyOneLyricsVerse(repeat, track)) {
717+
lyrics = chordRest->lyrics(0);
711718
} else {
712719
verseNumIt->second++;
713-
verseNum = verseNumIt->second;
720+
lyrics = chordRest->lyrics(verseNumIt->second);
714721
}
715722

716-
const Lyrics* lyrics = chordRest->lyrics(verseNum);
717723
if (lyrics) {
718724
updateSyllableMap(lyrics, segmentPositionTick);
719725
}
@@ -827,3 +833,22 @@ bool PlaybackContext::shouldSkipTrack(const track_idx_t trackIdx) const
827833
{
828834
return !muse::contains(m_usedVoices, track2voice(trackIdx));
829835
}
836+
837+
bool PlaybackContext::hasOnlyOneLyricsVerse(const RepeatSegment* repeat, const track_idx_t track) const
838+
{
839+
if (m_multiVerseLyricsPositionMap.empty()) {
840+
return true;
841+
}
842+
843+
const auto trackIt = m_multiVerseLyricsPositionMap.find(track);
844+
if (trackIt == m_multiVerseLyricsPositionMap.cend()) {
845+
return true;
846+
}
847+
848+
const int startTick = repeat->tick;
849+
const int endTick = repeat->endTick();
850+
const auto start = trackIt->second.lower_bound(startTick);
851+
const auto end = trackIt->second.lower_bound(endTick);
852+
853+
return start == end;
854+
}

src/engraving/playback/playbackcontext.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class Score;
3939
class MeasureRepeat;
4040
class TextBase;
4141
class ChordRest;
42+
class RepeatSegment;
4243

4344
class PlaybackContext
4445
{
@@ -97,13 +98,14 @@ class PlaybackContext
9798
const int tickPositionOffset);
9899
void handleHairpin(const Hairpin* hairpin, const int tickPositionOffset);
99100
void handleSegmentAnnotations(const ID partId, const Segment* segment, const int segmentPositionTick);
100-
void handleSegmentElements(const Segment* segment, const int segmentPositionTick,
101+
void handleSegmentElements(const RepeatSegment* repeat, const Segment* segment, const int segmentPositionTick,
101102
std::vector<const MeasureRepeat*>& foundMeasureRepeats);
102103
void handleMeasureRepeats(const std::vector<const MeasureRepeat*>& measureRepeats, const int tickPositionOffset);
103104

104105
void applyDynamic(const EngravingItem* dynamicItem, muse::mpe::dynamic_level_t dynamicLevel, const int positionTick);
105106

106107
bool shouldSkipTrack(const track_idx_t trackIdx) const;
108+
bool hasOnlyOneLyricsVerse(const RepeatSegment* repeat, const track_idx_t track) const;
107109

108110
track_idx_t m_partStartTrack = 0;
109111
track_idx_t m_partEndTrack = 0;
@@ -116,6 +118,7 @@ class PlaybackContext
116118
PlayTechniquesMap m_playTechniquesMap;
117119

118120
std::unordered_map<const ChordRest*, int> m_currentVerseNumByChordRest;
121+
std::unordered_map<track_idx_t, std::set<int /*tick*/> > m_multiVerseLyricsPositionMap;
119122
};
120123

121124
using PlaybackContextPtr = std::shared_ptr<PlaybackContext>;

src/engraving/playback/playbackmodel.cpp

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "dom/segment.h"
3535
#include "dom/tie.h"
3636
#include "dom/tremolotwochord.h"
37+
#include "dom/undo.h"
3738

3839
#include "log.h"
3940

@@ -979,22 +980,30 @@ bool PlaybackModel::shouldSkipChanges(const ScoreChanges& changes) const
979980
return false;
980981
}
981982

982-
const EngravingObject* obj = changes.changedObjects.begin()->first;
983-
if (!obj->isTextBase()) {
983+
const auto it = changes.changedObjects.begin();
984+
if (!it->first->isTextBase()) {
984985
return false;
985986
}
986987

987-
const TextBase* text = toTextBase(obj);
988-
const bool empty = toTextBase(obj)->empty();
988+
const TextBase* text = toTextBase(it->first);
989+
const bool empty = text->empty();
990+
if (!empty) {
991+
return false;
992+
}
989993

990-
if (empty && text->isHarmony() && m_playChordSymbols) {
994+
if (text->isHarmony() && m_playChordSymbols) {
991995
const InstrumentTrackId trackId = chordSymbolsTrackId(text->part()->id());
992996
if (!muse::contains(m_playbackDataMap, trackId)) {
993997
return false;
994998
}
995999
}
9961000

997-
return empty;
1001+
const std::unordered_set<CommandType>& commands = it->second;
1002+
if (muse::contains(commands, CommandType::RemoveElement)) {
1003+
return false;
1004+
}
1005+
1006+
return true;
9981007
}
9991008

10001009
PlaybackModel::TrackBoundaries PlaybackModel::trackBoundaries(const ScoreChanges& changes) const

src/engraving/tests/playback/playbackcontext_data/lyrics_multiverses.mscx

100755100644
Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<museScore version="4.60">
3-
<programVersion>4.6.0</programVersion>
3+
<programVersion>4.6.4</programVersion>
44
<programRevision></programRevision>
55
<Score>
66
<eid>NZ0ENYbWJhL_D1D+L5U0hlN</eid>
@@ -292,12 +292,53 @@
292292
</Measure>
293293
<Measure>
294294
<eid>xCh9L0aAXtB_9XbHTxI8fSO</eid>
295+
<startRepeat/>
296+
<endRepeat>2</endRepeat>
295297
<voice>
296-
<Rest>
297-
<eid>mFBXXtUiUJO_79AKUwrvGoB</eid>
298-
<durationType>measure</durationType>
299-
<duration>4/4</duration>
300-
</Rest>
298+
<Chord>
299+
<eid>JmHEThDyCzL_3Zr5iDsvUfB</eid>
300+
<durationType>quarter</durationType>
301+
<Lyrics>
302+
<eid>KCe0/GpKY3F_oZsG/NmoNxO</eid>
303+
<text>Hello</text>
304+
</Lyrics>
305+
<Note>
306+
<eid>/8PZnwmqnxI_mFgXhracsYO</eid>
307+
<pitch>69</pitch>
308+
<tpc>17</tpc>
309+
</Note>
310+
</Chord>
311+
<Chord>
312+
<eid>oeOTSUgFbqD_m+zfzkgo/iB</eid>
313+
<durationType>quarter</durationType>
314+
<Lyrics>
315+
<eid>uQIidy09HuL_CnqdRbJKDdE</eid>
316+
<text>world</text>
317+
</Lyrics>
318+
<Note>
319+
<eid>ybAxS3fYObE_TxK0/A0/2kE</eid>
320+
<pitch>70</pitch>
321+
<tpc>12</tpc>
322+
</Note>
323+
</Chord>
324+
<Chord>
325+
<eid>X5ROjBy5J4F_unAR8NaodzP</eid>
326+
<durationType>quarter</durationType>
327+
<Note>
328+
<eid>beQzD/isdpF_PW/gSx5L1DD</eid>
329+
<pitch>72</pitch>
330+
<tpc>14</tpc>
331+
</Note>
332+
</Chord>
333+
<Chord>
334+
<eid>YvrFXf97k3L_iMvHd1Dah3D</eid>
335+
<durationType>quarter</durationType>
336+
<Note>
337+
<eid>k4/6S1xKhw_bxDacXEvJR</eid>
338+
<pitch>74</pitch>
339+
<tpc>16</tpc>
340+
</Note>
341+
</Chord>
301342
</voice>
302343
</Measure>
303344
</Staff>

src/engraving/tests/playback/playbackcontext_tests.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -871,6 +871,14 @@ TEST_F(Engraving_PlaybackContextTests, Lyrics_Multiverses)
871871
{ 2500000, { makeSyllable(u"feel") } },
872872
{ 3000000, { makeSyllable(u"like") } },
873873
{ 3500000, { makeSyllable(u"work") } },
874+
875+
// 1st verse
876+
{ 4000000, { makeSyllable(u"Hello") } },
877+
{ 4500000, { makeSyllable(u"world") } },
878+
879+
// 1st verse (repeated)
880+
{ 6000000, { makeSyllable(u"Hello") } },
881+
{ 6500000, { makeSyllable(u"world") } },
874882
};
875883

876884
const std::map<timestamp_t, SyllableEventList> actualEvents = ctx.syllables(score);

0 commit comments

Comments
 (0)