Merge pull request #4556 from dmitrio95/fermata-time-stretch

Fix fermata time stretch handling on partial re-layout
This commit is contained in:
anatoly-os 2019-01-10 22:46:52 +02:00 committed by GitHub
commit 12902fd969
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 393 additions and 11 deletions

View file

@ -63,7 +63,6 @@ class Fraction {
Fraction operator+(const Fraction& v) const { return Fraction(*this) += v; }
Fraction operator-(const Fraction& v) const { return Fraction(*this) -= v; }
Fraction operator*(const Fraction& v) const { return Fraction(*this) *= v; }
Fraction operator*(int v) const { return Fraction(*this) *= v; }
Fraction operator/(const Fraction& v) const { return Fraction(*this) /= v; }
Fraction operator/(int v) const { return Fraction(*this) /= v; }
@ -79,6 +78,9 @@ class Fraction {
operator QVariant() const { return QVariant::fromValue(*this); }
};
inline Fraction operator*(const Fraction& f, int v) { return Fraction(f) *= v; }
inline Fraction operator*(int v, const Fraction& f) { return Fraction(f) *= v; }
#ifdef SCRIPT_INTERFACE
//---------------------------------------------------------

View file

@ -2657,6 +2657,11 @@ void Score::getNextMeasure(LayoutContext& lc)
}
measure->computeTicks();
// Reset tempo to set correct time stretch for fermata.
if (isMaster())
resetTempoRange(measure->tick(), measure->endTick());
for (Segment& segment : measure->segments()) {
if (segment.isBreathType()) {
qreal length = 0.0;
@ -2709,7 +2714,7 @@ void Score::getNextMeasure(LayoutContext& lc)
if (e->isFermata())
stretch = qMax(stretch, toFermata(e)->timeStretch());
else if (e->isTempoText()) {
if (score()->isMaster()) {
if (isMaster()) {
TempoText* tt = toTempoText(e);
setTempo(tt->segment(), tt->tempo());
}
@ -4187,11 +4192,6 @@ void Score::doLayoutRange(int stick, int etick)
lc.prevMeasure = 0;
// we need to reset tempo because fermata is setted
//inside getNextMeasure and it lead to twice timeStretch
if (isMaster())
resetTempoRange(stick, etick);
getNextMeasure(lc);
lc.curSystem = collectSystem(lc);

View file

@ -3315,11 +3315,12 @@ void Score::resetTempo()
void Score::resetTempoRange(int tick1, int tick2)
{
const bool zeroInRange = (tick1 <= 0 && tick2 > 0);
tempomap()->clearRange(tick1, tick2);
if (tempomap()->empty())
if (zeroInRange)
tempomap()->setTempo(0, _defaultTempo);
sigmap()->clearRange(tick1, tick2);
if (sigmap()->empty()) {
if (zeroInRange) {
Measure* m = firstMeasure();
if (m)
sigmap()->add(0, SigEvent(m->len(), m->timesig(), 0));

Binary file not shown.

View file

@ -0,0 +1,340 @@
<?xml version="1.0" encoding="UTF-8"?>
<museScore version="3.01">
<programVersion>3.0.1</programVersion>
<programRevision>6d522ee</programRevision>
<Score>
<LayerTag id="0" tag="default"></LayerTag>
<currentLayer>0</currentLayer>
<Synthesizer>
</Synthesizer>
<Division>480</Division>
<Style>
<pageWidth>8.27</pageWidth>
<pageHeight>11.69</pageHeight>
<pagePrintableWidth>7.4826</pagePrintableWidth>
<lastSystemFillLimit>0</lastSystemFillLimit>
<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="creationDate">2018-11-12</metaTag>
<metaTag name="lyricist"></metaTag>
<metaTag name="movementNumber"></metaTag>
<metaTag name="movementTitle"></metaTag>
<metaTag name="platform">Linux</metaTag>
<metaTag name="poet"></metaTag>
<metaTag name="source"></metaTag>
<metaTag name="translator"></metaTag>
<metaTag name="workNumber"></metaTag>
<metaTag name="workTitle">Treble</metaTag>
<Part>
<Staff id="1">
<StaffType group="pitched">
<name>stdNormal</name>
</StaffType>
</Staff>
<trackName>Piano</trackName>
<Instrument>
<longName>Piano</longName>
<shortName>Pno.</shortName>
<trackName>Piano</trackName>
<minPitchP>21</minPitchP>
<maxPitchP>108</maxPitchP>
<minPitchA>21</minPitchA>
<maxPitchA>108</maxPitchA>
<instrumentId>keyboard.piano</instrumentId>
<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"/>
<synti>Fluid</synti>
</Channel>
</Instrument>
</Part>
<Staff id="1">
<VBox>
<height>10</height>
<Text>
<style>Title</style>
<text>Treble</text>
</Text>
</VBox>
<Measure>
<voice>
<TimeSig>
<sigN>4</sigN>
<sigD>4</sigD>
</TimeSig>
<Fermata>
<subtype>fermataAbove</subtype>
<timeStretch>2</timeStretch>
</Fermata>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>69</pitch>
<tpc>17</tpc>
</Note>
</Chord>
<Fermata>
<subtype>fermataAbove</subtype>
<timeStretch>3</timeStretch>
</Fermata>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>69</pitch>
<tpc>17</tpc>
</Note>
</Chord>
<Fermata>
<subtype>fermataAbove</subtype>
</Fermata>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>69</pitch>
<tpc>17</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>69</pitch>
<tpc>17</tpc>
</Note>
</Chord>
</voice>
</Measure>
<Measure>
<voice>
<Rest>
<durationType>measure</durationType>
<duration>4/4</duration>
</Rest>
</voice>
</Measure>
<Measure>
<voice>
<Fermata>
<subtype>fermataAbove</subtype>
<timeStretch>2</timeStretch>
</Fermata>
<Tempo>
<tempo>2.5</tempo>
<followText>1</followText>
<text><b></b><font face="ScoreText"></font><b><font face="FreeSerif"></font> = 150</b></text>
</Tempo>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>69</pitch>
<tpc>17</tpc>
</Note>
</Chord>
<Fermata>
<subtype>fermataAbove</subtype>
<timeStretch>3</timeStretch>
</Fermata>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>69</pitch>
<tpc>17</tpc>
</Note>
</Chord>
<Fermata>
<subtype>fermataAbove</subtype>
</Fermata>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>69</pitch>
<tpc>17</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>69</pitch>
<tpc>17</tpc>
</Note>
</Chord>
</voice>
</Measure>
<Measure>
<voice>
<Fermata>
<subtype>fermataAbove</subtype>
<timeStretch>2</timeStretch>
</Fermata>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>69</pitch>
<tpc>17</tpc>
</Note>
</Chord>
<Fermata>
<subtype>fermataAbove</subtype>
<timeStretch>3</timeStretch>
</Fermata>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>69</pitch>
<tpc>17</tpc>
</Note>
</Chord>
<Fermata>
<subtype>fermataAbove</subtype>
</Fermata>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>69</pitch>
<tpc>17</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>69</pitch>
<tpc>17</tpc>
</Note>
</Chord>
</voice>
</Measure>
<Measure>
<voice>
<Rest>
<durationType>measure</durationType>
<duration>4/4</duration>
</Rest>
</voice>
</Measure>
<Measure>
<voice>
<Fermata>
<subtype>fermataAbove</subtype>
<timeStretch>2</timeStretch>
</Fermata>
<Tempo>
<tempo>0.5</tempo>
<followText>1</followText>
<text><b></b><font face="ScoreText"></font><b><font face="FreeSerif"></font> = 30</b></text>
</Tempo>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>69</pitch>
<tpc>17</tpc>
</Note>
</Chord>
<Fermata>
<subtype>fermataAbove</subtype>
<timeStretch>3</timeStretch>
</Fermata>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>69</pitch>
<tpc>17</tpc>
</Note>
</Chord>
<Fermata>
<subtype>fermataAbove</subtype>
</Fermata>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>69</pitch>
<tpc>17</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>69</pitch>
<tpc>17</tpc>
</Note>
</Chord>
</voice>
</Measure>
<Measure>
<voice>
<Fermata>
<subtype>fermataAbove</subtype>
<timeStretch>2</timeStretch>
</Fermata>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>69</pitch>
<tpc>17</tpc>
</Note>
</Chord>
<Fermata>
<subtype>fermataAbove</subtype>
<timeStretch>3</timeStretch>
</Fermata>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>69</pitch>
<tpc>17</tpc>
</Note>
</Chord>
<Fermata>
<subtype>fermataAbove</subtype>
</Fermata>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>69</pitch>
<tpc>17</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>69</pitch>
<tpc>17</tpc>
</Note>
</Chord>
</voice>
</Measure>
</Staff>
</Score>
</museScore>

View file

@ -43,6 +43,7 @@ class TestMidi : public QObject, public MTest
{
Q_OBJECT
void midiExportTestRef(const QString& file);
void testMidiExport(MasterScore* score, const QString& writeFile, const QString& refFile);
private slots:
void initTestCase();
@ -67,6 +68,7 @@ class TestMidi : public QObject, public MTest
midiExportTestRef("testVoltaDynamic"); // test changing Dynamic in prima and seconda volta
midiExportTestRef("testVoltaStaffText"); // test changing StaffText in prima and seconda volta
}
void midiTimeStretchFermata();
};
//---------------------------------------------------------
@ -364,6 +366,31 @@ void TestMidi::midi03()
delete score2;
}
//---------------------------------------------------------
// midiTimeStretchFermata
//---------------------------------------------------------
void TestMidi::midiTimeStretchFermata()
{
const QString file("testTimeStretchFermata");
QString readFile(DIR + file + ".mscx");
QString writeFile(file + "-test-%1.mid");
QString reference(DIR + file + "-ref.mid");
MasterScore* score = readScore(readFile);
testMidiExport(score, writeFile.arg(1), reference);
const Fraction frac1 = 2 * Fraction(4, 4) + Fraction(2, 4); // 3rd measure, 3rd beat
score->doLayoutRange(frac1.ticks(), frac1.ticks());
testMidiExport(score, writeFile.arg(2), reference);
const Fraction frac2 = 6 * Fraction(4, 4); // 7th measure
score->doLayoutRange(frac2.ticks(), frac2.ticks());
testMidiExport(score, writeFile.arg(3), reference);
delete score;
}
//---------------------------------------------------------
// events
//---------------------------------------------------------
@ -404,6 +431,19 @@ void TestMidi::events()
QVERIFY(score);
QVERIFY(compareFiles(writeFile, reference));
// QVERIFY(saveCompareScore(score, writeFile, reference));
delete score;
}
//---------------------------------------------------------
// testMidiExport
//---------------------------------------------------------
void TestMidi::testMidiExport(MasterScore* score, const QString& writeFile, const QString& refFile)
{
Q_ASSERT(writeFile.endsWith(".mid") && refFile.endsWith(".mid"));
QVERIFY(saveMidi(score, writeFile));
QVERIFY(compareFiles(writeFile, refFile));
}
//---------------------------------------------------------
@ -418,8 +458,7 @@ void TestMidi::midiExportTestRef(const QString& file)
QVERIFY(score);
score->doLayout();
score->rebuildMidiMapping();
QVERIFY(saveMidi(score, QString(file) + ".mid"));
QVERIFY(compareFiles(QString(file) + ".mid", DIR + QString(file) + "-ref.mid"));
testMidiExport(score, QString(file) + ".mid", DIR + QString(file) + "-ref.mid");
delete score;
}