Merge pull request #4556 from dmitrio95/fermata-time-stretch
Fix fermata time stretch handling on partial re-layout
This commit is contained in:
commit
12902fd969
6 changed files with 393 additions and 11 deletions
|
@ -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
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
BIN
mtest/libmscore/midi/testTimeStretchFermata-ref.mid
Normal file
BIN
mtest/libmscore/midi/testTimeStretchFermata-ref.mid
Normal file
Binary file not shown.
340
mtest/libmscore/midi/testTimeStretchFermata.mscx
Normal file
340
mtest/libmscore/midi/testTimeStretchFermata.mscx
Normal 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>
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue