Fix #49881 - Glissando to wrong note if other notes in other voices

Original issue: http://musescore.org/en/node/49881

Adding a glissando to a note encompassing intervening notes in other voices or staves of the same instrument, the glissando ends into the first intervening note in another voice / staff, rather than on the 'obvious' end note in the same voice / staff.

Fixed and added more tests for these cases.
This commit is contained in:
Maurizio M. Gavioli 2015-03-09 13:47:02 +01:00
parent ced591e7c7
commit 5b32a3c18d
4 changed files with 841 additions and 9 deletions

View file

@ -630,6 +630,9 @@ Note* Glissando::guessFinalNote(Chord* chord)
case NoteType::INVALID:
return nullptr;
// for grace notes before, return top note of parent chord
// TODO : if the grace-before is not the LAST ONE, this still returns the main note
// which is probably not correct; however a glissando between two grace notes
// probably makes little sense.
case NoteType::ACCIACCATURA:
case NoteType::APPOGGIATURA:
case NoteType::GRACE4:
@ -640,6 +643,7 @@ Note* Glissando::guessFinalNote(Chord* chord)
else // no parent or parent is not a chord?
return nullptr;
// for grace notes after, next chord is next chord of parent chord
// TODO : same note as case above!
case NoteType::GRACE8_AFTER:
case NoteType::GRACE16_AFTER:
case NoteType::GRACE32_AFTER:
@ -663,11 +667,10 @@ Note* Glissando::guessFinalNote(Chord* chord)
if (chord->parent()->type() != Element::Type::SEGMENT)
return nullptr;
// look for first ChordRest segment after initial note is elapsed
Segment* segm = chord->score()->tick2rightSegment(chord->tick() + chord->actualTicks());
int chordTrack = chord->track();
Segment* segm = chord->segment();
Part* part = chord->staff()->part();
if (segm != nullptr)
segm = segm->next1();
while (segm) {
// if next segment is a ChordRest segment
if (segm->segmentType() == Segment::Type::ChordRest) {

View file

@ -0,0 +1,385 @@
<?xml version="1.0" encoding="UTF-8"?>
<museScore version="2.00">
<Score>
<LayerTag id="0" tag="default"></LayerTag>
<currentLayer>0</currentLayer>
<Division>480</Division>
<Style>
<TextStyle>
<halign>left</halign>
<valign>top</valign>
<xoffset>0</xoffset>
<yoffset>-6</yoffset>
<offsetType>spatium</offsetType>
<name>Staff</name>
<family>FreeSerif</family>
<size>10</size>
<sizeIsSpatiumDependent>1</sizeIsSpatiumDependent>
</TextStyle>
<page-layout>
<page-height>1683.78</page-height>
<page-width>1190.55</page-width>
<page-margins type="even">
<left-margin>56.6929</left-margin>
<right-margin>56.6929</right-margin>
<top-margin>56.6929</top-margin>
<bottom-margin>113.386</bottom-margin>
</page-margins>
<page-margins type="odd">
<left-margin>56.6929</left-margin>
<right-margin>56.6929</right-margin>
<top-margin>56.6929</top-margin>
<bottom-margin>113.386</bottom-margin>
</page-margins>
</page-layout>
<Spatium>1.76389</Spatium>
</Style>
<showInvisible>1</showInvisible>
<showUnprintable>1</showUnprintable>
<showFrames>1</showFrames>
<showMargins>0</showMargins>
<metaTag name="arranger"></metaTag>
<metaTag name="composer"></metaTag>
<metaTag name="copyright"></metaTag>
<metaTag name="lyricist"></metaTag>
<metaTag name="movementNumber"></metaTag>
<metaTag name="movementTitle"></metaTag>
<metaTag name="poet"></metaTag>
<metaTag name="source"></metaTag>
<metaTag name="translator"></metaTag>
<metaTag name="workNumber"></metaTag>
<metaTag name="workTitle"></metaTag>
<PageList>
<Page>
<System>
</System>
</Page>
</PageList>
<Part>
<Staff id="1">
<StaffType group="pitched">
<name>stdNormal</name>
</StaffType>
<bracket type="1" span="2"/>
<barLineSpan>2</barLineSpan>
</Staff>
<Staff id="2">
<StaffType group="pitched">
<name>stdNormal</name>
</StaffType>
<defaultClef>F</defaultClef>
<bracket type="-1" span="0"/>
<barLineSpan>0</barLineSpan>
</Staff>
<trackName>Piano</trackName>
<Instrument>
<longName pos="0">Piano</longName>
<shortName pos="0">Pno.</shortName>
<trackName>Piano</trackName>
<minPitchP>21</minPitchP>
<maxPitchP>108</maxPitchP>
<minPitchA>21</minPitchA>
<maxPitchA>108</maxPitchA>
<instrumentId>keyboard.piano</instrumentId>
<clef staff="2">F</clef>
<Articulation>
<velocity>100</velocity>
<gateTime>95</gateTime>
</Articulation>
<Articulation name="staccatissimo">
<velocity>100</velocity>
<gateTime>33</gateTime>
</Articulation>
<Articulation name="staccato">
<velocity>100</velocity>
<gateTime>50</gateTime>
</Articulation>
<Articulation name="portato">
<velocity>100</velocity>
<gateTime>67</gateTime>
</Articulation>
<Articulation name="tenuto">
<velocity>100</velocity>
<gateTime>100</gateTime>
</Articulation>
<Articulation name="marcato">
<velocity>120</velocity>
<gateTime>67</gateTime>
</Articulation>
<Articulation name="sforzato">
<velocity>120</velocity>
<gateTime>100</gateTime>
</Articulation>
<Channel>
<program value="0"/>
</Channel>
</Instrument>
</Part>
<Staff id="1">
<Measure number="1">
<TimeSig>
<sigN>2</sigN>
<sigD>4</sigD>
<showCourtesySig>0</showCourtesySig>
</TimeSig>
<StaffText>
<text>Simple case</text>
</StaffText>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>72</pitch>
<tpc>14</tpc>
<Glissando id="2">
<text>gliss.</text>
<subtype>0</subtype>
<diagonal>1</diagonal>
<lineWidth>0.15</lineWidth>
<anchor>3</anchor>
</Glissando>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>84</pitch>
<tpc>14</tpc>
<endSpanner id="2"/>
</Note>
</Chord>
</Measure>
<Measure number="2">
<StaffText>
<text>Down-staff</text>
</StaffText>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>72</pitch>
<tpc>14</tpc>
<Glissando id="3">
<text>gliss.</text>
<subtype>0</subtype>
<diagonal>1</diagonal>
<lineWidth>0.15</lineWidth>
<anchor>3</anchor>
</Glissando>
</Note>
</Chord>
<Rest>
<durationType>quarter</durationType>
</Rest>
</Measure>
<Measure number="3">
<StaffText>
<text>Up-staff</text>
</StaffText>
<Rest>
<durationType>quarter</durationType>
</Rest>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>72</pitch>
<tpc>14</tpc>
<endSpanner id="4"/>
</Note>
</Chord>
</Measure>
<Measure number="4">
<StaffText>
<text>Intervening notes
in other voice</text>
</StaffText>
<Chord>
<durationType>half</durationType>
<Note>
<pitch>72</pitch>
<tpc>14</tpc>
<Glissando id="5">
<text>gliss.</text>
<subtype>0</subtype>
<diagonal>1</diagonal>
<lineWidth>0.15</lineWidth>
<anchor>3</anchor>
</Glissando>
</Note>
</Chord>
<tick>2880</tick>
<Chord>
<track>1</track>
<durationType>quarter</durationType>
<Note>
<track>1</track>
<pitch>67</pitch>
<tpc>15</tpc>
</Note>
</Chord>
<Chord>
<track>1</track>
<durationType>quarter</durationType>
<Note>
<track>1</track>
<pitch>67</pitch>
<tpc>15</tpc>
</Note>
</Chord>
</Measure>
<Measure number="5">
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>84</pitch>
<tpc>14</tpc>
<endSpanner id="5"/>
</Note>
</Chord>
<Rest>
<durationType>quarter</durationType>
</Rest>
<tick>3840</tick>
<Chord>
<track>1</track>
<durationType>quarter</durationType>
<Note>
<track>1</track>
<pitch>67</pitch>
<tpc>15</tpc>
</Note>
</Chord>
<Rest>
<track>1</track>
<durationType>quarter</durationType>
</Rest>
</Measure>
<Measure number="6">
<StaffText>
<text>Intervening notes
in other staff</text>
</StaffText>
<Chord>
<durationType>half</durationType>
<Note>
<pitch>72</pitch>
<tpc>14</tpc>
<Glissando id="6">
<text>gliss.</text>
<subtype>0</subtype>
<diagonal>1</diagonal>
<lineWidth>0.15</lineWidth>
<anchor>3</anchor>
</Glissando>
</Note>
</Chord>
</Measure>
<Measure number="7">
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>84</pitch>
<tpc>14</tpc>
<endSpanner id="6"/>
</Note>
</Chord>
<Rest>
<durationType>quarter</durationType>
</Rest>
</Measure>
<Measure number="8">
<Rest>
<durationType>measure</durationType>
<duration z="2" n="4"/>
</Rest>
<BarLine>
<subtype>end</subtype>
<span>2</span>
</BarLine>
</Measure>
</Staff>
<Staff id="2">
<Measure number="1">
<TimeSig>
<sigN>2</sigN>
<sigD>4</sigD>
<showCourtesySig>0</showCourtesySig>
</TimeSig>
<Rest>
<durationType>measure</durationType>
<duration z="2" n="4"/>
</Rest>
</Measure>
<Measure number="2">
<Rest>
<durationType>quarter</durationType>
</Rest>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>48</pitch>
<tpc>14</tpc>
<endSpanner id="3"/>
</Note>
</Chord>
</Measure>
<Measure number="3">
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>48</pitch>
<tpc>14</tpc>
<Glissando id="4">
<text>gliss.</text>
<subtype>0</subtype>
<diagonal>1</diagonal>
<lineWidth>0.15</lineWidth>
<anchor>3</anchor>
</Glissando>
</Note>
</Chord>
<Rest>
<durationType>quarter</durationType>
</Rest>
</Measure>
<Measure number="4">
<Rest>
<durationType>measure</durationType>
<duration z="2" n="4"/>
</Rest>
</Measure>
<Measure number="5">
<Rest>
<durationType>measure</durationType>
<duration z="2" n="4"/>
</Rest>
</Measure>
<Measure number="6">
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>48</pitch>
<tpc>14</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>48</pitch>
<tpc>14</tpc>
</Note>
</Chord>
</Measure>
<Measure number="7">
<Rest>
<durationType>measure</durationType>
<duration z="2" n="4"/>
</Rest>
</Measure>
<Measure number="8">
<Rest>
<durationType>measure</durationType>
<duration z="2" n="4"/>
</Rest>
</Measure>
</Staff>
</Score>
</museScore>

View file

@ -0,0 +1,345 @@
<?xml version="1.0" encoding="UTF-8"?>
<museScore version="2.00">
<Score>
<LayerTag id="0" tag="default"></LayerTag>
<currentLayer>0</currentLayer>
<Division>480</Division>
<Style>
<TextStyle>
<halign>left</halign>
<valign>top</valign>
<xoffset>0</xoffset>
<yoffset>-6</yoffset>
<offsetType>spatium</offsetType>
<name>Staff</name>
<family>FreeSerif</family>
<size>10</size>
<sizeIsSpatiumDependent>1</sizeIsSpatiumDependent>
</TextStyle>
<page-layout>
<page-height>1683.78</page-height>
<page-width>1190.55</page-width>
<page-margins type="even">
<left-margin>56.6929</left-margin>
<right-margin>56.6929</right-margin>
<top-margin>56.6929</top-margin>
<bottom-margin>113.386</bottom-margin>
</page-margins>
<page-margins type="odd">
<left-margin>56.6929</left-margin>
<right-margin>56.6929</right-margin>
<top-margin>56.6929</top-margin>
<bottom-margin>113.386</bottom-margin>
</page-margins>
</page-layout>
<Spatium>1.76389</Spatium>
</Style>
<showInvisible>1</showInvisible>
<showUnprintable>1</showUnprintable>
<showFrames>1</showFrames>
<showMargins>0</showMargins>
<metaTag name="arranger"></metaTag>
<metaTag name="composer"></metaTag>
<metaTag name="copyright"></metaTag>
<metaTag name="lyricist"></metaTag>
<metaTag name="movementNumber"></metaTag>
<metaTag name="movementTitle"></metaTag>
<metaTag name="poet"></metaTag>
<metaTag name="source"></metaTag>
<metaTag name="translator"></metaTag>
<metaTag name="workNumber"></metaTag>
<metaTag name="workTitle"></metaTag>
<PageList>
<Page>
<System>
</System>
</Page>
</PageList>
<Part>
<Staff id="1">
<StaffType group="pitched">
<name>stdNormal</name>
</StaffType>
<bracket type="1" span="2"/>
<barLineSpan>2</barLineSpan>
</Staff>
<Staff id="2">
<StaffType group="pitched">
<name>stdNormal</name>
</StaffType>
<defaultClef>F</defaultClef>
<bracket type="-1" span="0"/>
<barLineSpan>0</barLineSpan>
</Staff>
<trackName>Piano</trackName>
<Instrument>
<longName pos="0">Piano</longName>
<shortName pos="0">Pno.</shortName>
<trackName>Piano</trackName>
<minPitchP>21</minPitchP>
<maxPitchP>108</maxPitchP>
<minPitchA>21</minPitchA>
<maxPitchA>108</maxPitchA>
<instrumentId>keyboard.piano</instrumentId>
<clef staff="2">F</clef>
<Articulation>
<velocity>100</velocity>
<gateTime>95</gateTime>
</Articulation>
<Articulation name="staccatissimo">
<velocity>100</velocity>
<gateTime>33</gateTime>
</Articulation>
<Articulation name="staccato">
<velocity>100</velocity>
<gateTime>50</gateTime>
</Articulation>
<Articulation name="portato">
<velocity>100</velocity>
<gateTime>67</gateTime>
</Articulation>
<Articulation name="tenuto">
<velocity>100</velocity>
<gateTime>100</gateTime>
</Articulation>
<Articulation name="marcato">
<velocity>120</velocity>
<gateTime>67</gateTime>
</Articulation>
<Articulation name="sforzato">
<velocity>120</velocity>
<gateTime>100</gateTime>
</Articulation>
<Channel>
<program value="0"/>
</Channel>
</Instrument>
</Part>
<Staff id="1">
<Measure number="1">
<TimeSig>
<sigN>2</sigN>
<sigD>4</sigD>
<showCourtesySig>0</showCourtesySig>
</TimeSig>
<StaffText>
<text>Simple case</text>
</StaffText>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>72</pitch>
<tpc>14</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>84</pitch>
<tpc>14</tpc>
</Note>
</Chord>
</Measure>
<Measure number="2">
<StaffText>
<text>Down-staff</text>
</StaffText>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>72</pitch>
<tpc>14</tpc>
</Note>
</Chord>
<Rest>
<durationType>quarter</durationType>
</Rest>
</Measure>
<Measure number="3">
<StaffText>
<text>Up-staff</text>
</StaffText>
<Rest>
<durationType>quarter</durationType>
</Rest>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>72</pitch>
<tpc>14</tpc>
</Note>
</Chord>
</Measure>
<Measure number="4">
<StaffText>
<text>Intervening notes
in other voice</text>
</StaffText>
<Chord>
<durationType>half</durationType>
<Note>
<pitch>72</pitch>
<tpc>14</tpc>
</Note>
</Chord>
<tick>2880</tick>
<Chord>
<track>1</track>
<durationType>quarter</durationType>
<Note>
<track>1</track>
<pitch>67</pitch>
<tpc>15</tpc>
</Note>
</Chord>
<Chord>
<track>1</track>
<durationType>quarter</durationType>
<Note>
<track>1</track>
<pitch>67</pitch>
<tpc>15</tpc>
</Note>
</Chord>
</Measure>
<Measure number="5">
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>84</pitch>
<tpc>14</tpc>
</Note>
</Chord>
<Rest>
<durationType>quarter</durationType>
</Rest>
<tick>3840</tick>
<Chord>
<track>1</track>
<durationType>quarter</durationType>
<Note>
<track>1</track>
<pitch>67</pitch>
<tpc>15</tpc>
</Note>
</Chord>
<Rest>
<track>1</track>
<durationType>quarter</durationType>
</Rest>
</Measure>
<Measure number="6">
<StaffText>
<text>Intervening notes
in other staff</text>
</StaffText>
<Chord>
<durationType>half</durationType>
<Note>
<pitch>72</pitch>
<tpc>14</tpc>
</Note>
</Chord>
</Measure>
<Measure number="7">
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>84</pitch>
<tpc>14</tpc>
</Note>
</Chord>
<Rest>
<durationType>quarter</durationType>
</Rest>
</Measure>
<Measure number="8">
<Rest>
<durationType>measure</durationType>
<duration z="2" n="4"/>
</Rest>
<BarLine>
<subtype>end</subtype>
<span>2</span>
</BarLine>
</Measure>
</Staff>
<Staff id="2">
<Measure number="1">
<TimeSig>
<sigN>2</sigN>
<sigD>4</sigD>
<showCourtesySig>0</showCourtesySig>
</TimeSig>
<Rest>
<durationType>measure</durationType>
<duration z="2" n="4"/>
</Rest>
</Measure>
<Measure number="2">
<Rest>
<durationType>quarter</durationType>
</Rest>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>48</pitch>
<tpc>14</tpc>
</Note>
</Chord>
</Measure>
<Measure number="3">
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>48</pitch>
<tpc>14</tpc>
</Note>
</Chord>
<Rest>
<durationType>quarter</durationType>
</Rest>
</Measure>
<Measure number="4">
<Rest>
<durationType>measure</durationType>
<duration z="2" n="4"/>
</Rest>
</Measure>
<Measure number="5">
<Rest>
<durationType>measure</durationType>
<duration z="2" n="4"/>
</Rest>
</Measure>
<Measure number="6">
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>48</pitch>
<tpc>14</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>48</pitch>
<tpc>14</tpc>
</Note>
</Chord>
</Measure>
<Measure number="7">
<Rest>
<durationType>measure</durationType>
<duration z="2" n="4"/>
</Rest>
</Measure>
<Measure number="8">
<Rest>
<durationType>measure</durationType>
<duration z="2" n="4"/>
</Rest>
</Measure>
</Staff>
</Score>
</museScore>

View file

@ -24,7 +24,7 @@
using namespace Ms;
//---------------------------------------------------------
// TestClef
// TestSpanners
//---------------------------------------------------------
class TestSpanners : public QObject, public MTest
@ -33,8 +33,9 @@ class TestSpanners : public QObject, public MTest
private slots:
void initTestCase();
void spanners01(); // cross-staff glissando from lower to higher staff
void spanners02(); // glissando from/to grace notes
void spanners01(); // adding glissandos in several contexts
void spanners02(); // loading back existing cross-staff glissando from lower to higher staff
void spanners03(); // adding glissandos from/to grace notes
};
//---------------------------------------------------------
@ -48,6 +49,104 @@ void TestSpanners::initTestCase()
//---------------------------------------------------------
/// spanners01
/// Adds glissandi in several contexts.
//---------------------------------------------------------
void TestSpanners::spanners01()
{
DropData dropData;
Glissando* gliss;
Score* score = readScore(DIR + "glissando01.mscx");
QVERIFY(score);
score->doLayout();
// SIMPLE CASE: GLISSANDO FROM A NOTE TO THE FOLLOWING
// go to top note of first chord
Measure* msr = score->firstMeasure();
QVERIFY(msr);
Segment* seg = msr->findSegment(Segment::Type::ChordRest, 0);
QVERIFY(seg);
Chord* chord = static_cast<Chord*>(seg->element(0));
QVERIFY(chord && chord->type() == Element::Type::CHORD);
Note* note = chord->upNote();
QVERIFY(note);
// drop a glissando on note
gliss = new Glissando(score); // create a new element each time, as drop() will eventually delete it
dropData.pos = note->pagePos();
dropData.element = gliss;
note->drop(dropData);
// GLISSANDO FROM TOP STAFF TO BOTTOM STAFF
// go to top note of first chord of next measure
msr = msr->nextMeasure();
QVERIFY(msr);
seg = msr->first();
QVERIFY(seg);
chord = static_cast<Chord*>(seg->element(0)); // voice 0 of staff 0
QVERIFY(chord && chord->type() == Element::Type::CHORD);
note = chord->upNote();
QVERIFY(note);
// drop a glissando on note
gliss = new Glissando(score);
dropData.pos = note->pagePos();
dropData.element = gliss;
note->drop(dropData);
// GLISSANDO FROM BOTTOM STAFF TO TOP STAFF
// go to bottom note of first chord of next measure
msr = msr->nextMeasure();
QVERIFY(msr);
seg = msr->first();
QVERIFY(seg);
chord = static_cast<Chord*>(seg->element(4)); // voice 0 of staff 1
QVERIFY(chord && chord->type() == Element::Type::CHORD);
note = chord->upNote();
QVERIFY(note);
// drop a glissando on note
gliss = new Glissando(score);
dropData.pos = note->pagePos();
dropData.element = gliss;
note->drop(dropData);
// GLISSANDO OVER INTERVENING NOTES IN ANOTHER VOICE
// go to top note of first chord of next measure
msr = msr->nextMeasure();
QVERIFY(msr);
seg = msr->first();
QVERIFY(seg);
chord = static_cast<Chord*>(seg->element(0)); // voice 0 of staff 0
QVERIFY(chord && chord->type() == Element::Type::CHORD);
note = chord->upNote();
QVERIFY(note);
// drop a glissando on note
gliss = new Glissando(score);
dropData.pos = note->pagePos();
dropData.element = gliss;
note->drop(dropData);
// GLISSANDO OVER INTERVENING NOTES IN ANOTHER STAFF
// go to top note of first chord of next measure
msr = msr->nextMeasure()->nextMeasure();
QVERIFY(msr);
seg = msr->first();
QVERIFY(seg);
chord = static_cast<Chord*>(seg->element(0)); // voice 0 of staff 0
QVERIFY(chord && chord->type() == Element::Type::CHORD);
note = chord->upNote();
QVERIFY(note);
// drop a glissando on note
gliss = new Glissando(score);
dropData.pos = note->pagePos();
dropData.element = gliss;
note->drop(dropData);
QVERIFY(saveCompareScore(score, "glissando01.mscx", DIR + "glissando01-ref.mscx"));
delete score;
}
//---------------------------------------------------------
/// spanners02
/// Check loading of score with a glissando from a lower to a higher staff:
// A score with:
// grand staff,
@ -55,7 +154,7 @@ void TestSpanners::initTestCase()
// is loaded and laid out and saved: should be round-trip safe.
//---------------------------------------------------------
void TestSpanners::spanners01()
void TestSpanners::spanners02()
{
Score* score = readScore(DIR + "glissando-crossstaff01.mscx");
QVERIFY(score);
@ -66,11 +165,11 @@ void TestSpanners::spanners01()
}
//---------------------------------------------------------
/// spanners02
/// spanners03
/// Loads a score with before- and after-grace notes and adds several glissandi from/to them.
//---------------------------------------------------------
void TestSpanners::spanners02()
void TestSpanners::spanners03()
{
DropData dropData;
Glissando* gliss;