Skip to content

Commit

Permalink
ENG-5: infer subtitles
Browse files Browse the repository at this point in the history
Dolet commonly exports subtitle text as staff text attached to a beat
near the beginning of the score. This commit adds regex-based
inferencing for this case, adding the text to a new subtitle in the
beginning VBox of the score.

Duplicate of musescore#8413, part 1
  • Loading branch information
iveshenry18 authored and Jojo-Schmitz committed Aug 19, 2021
1 parent 16402be commit 51c73cc
Show file tree
Hide file tree
Showing 7 changed files with 449 additions and 4 deletions.
6 changes: 3 additions & 3 deletions importexport/musicxml/importmxmlpass1.cpp
Expand Up @@ -639,7 +639,7 @@ static Tid tidForCreditWords(const CreditWords* const word, std::vector<const Cr
// createAndAddVBoxForCreditWords
//---------------------------------------------------------

static VBox* createAndAddVBoxForCreditWords(Score* const score, const int miny = 0, const int maxy = 75)
VBox* MusicXMLParserPass1::createAndAddVBoxForCreditWords(Score* const score, const int miny, const int maxy)
{
auto vbox = new VBox(score);
qreal vboxHeight = 10; // default height in tenths
Expand Down Expand Up @@ -716,7 +716,7 @@ static VBox* addCreditWords(Score* const score, const CreditWordsList& crWords,
const auto tid = (pageNr == 1 && top) ? tidForCreditWords(w, words, pageSize.width()) : Tid::DEFAULT;
double yoffs = (maxy - w->defaultY) * score->spatium() / 10;
if (!vbox)
vbox = createAndAddVBoxForCreditWords(score, miny, maxy);
vbox = MusicXMLParserPass1::createAndAddVBoxForCreditWords(score, miny, maxy);
addText2(vbox, score, w->words, tid, align, yoffs);
}
}
Expand Down Expand Up @@ -754,7 +754,7 @@ static void createDefaultHeader(Score* const score)
if (!metaPoet.isEmpty()) strPoet = metaPoet;
if (!metaTranslator.isEmpty()) strTranslator = metaTranslator;

const auto vbox = createAndAddVBoxForCreditWords(score);
const auto vbox = MusicXMLParserPass1::createAndAddVBoxForCreditWords(score);
addText(vbox, score, strTitle.toHtmlEscaped(), Tid::TITLE);
addText(vbox, score, strSubTitle.toHtmlEscaped(), Tid::SUBTITLE);
addText(vbox, score, strComposer.toHtmlEscaped(), Tid::COMPOSER);
Expand Down
1 change: 1 addition & 0 deletions importexport/musicxml/importmxmlpass1.h
Expand Up @@ -166,6 +166,7 @@ class MusicXMLParserPass1 {
int octaveShift(const QString& id, const int staff, const Fraction f) const;
const CreditWordsList& credits() const { return _credits; }
bool hasBeamingInfo() const { return _hasBeamingInfo; }
static VBox* createAndAddVBoxForCreditWords(Score* const score, const int miny = 0, const int maxy = 75);

private:
// functions
Expand Down
25 changes: 24 additions & 1 deletion importexport/musicxml/importmxmlpass2.cpp
Expand Up @@ -22,6 +22,7 @@

#include "libmscore/arpeggio.h"
#include "libmscore/accidental.h"
#include "libmscore/box.h"
#include "libmscore/breath.h"
#include "libmscore/chord.h"
#include "libmscore/chordline.h"
Expand Down Expand Up @@ -71,6 +72,7 @@
#include "importmxmlnoteduration.h"
#include "importmxmlnotepitch.h"
#include "importmxmlpass2.h"
#include "importmxmlpass1.h"
#include "musicxmlfonthandler.h"
#include "musicxmlsupport.h"

Expand Down Expand Up @@ -2527,7 +2529,15 @@ void MusicXMLParserDirection::direction(const QString& partId,
// qPrintable(_wordsText), qPrintable(_rehearsalText), qPrintable(_metroText), _tpoSound);

// create text if any text was found
if (_wordsText != "" || _rehearsalText != "" || _metroText != "") {
if (isLikelyCredit(tick)) {
Text* t = new Text(_score, Tid::SUBTITLE);
t->setLayoutToParentWidth(true);
t->setXmlText(_wordsText);
auto firstMeasure = _score->measures()->first();
VBox* vbox = firstMeasure->isVBox() ? toVBox(firstMeasure) : MusicXMLParserPass1::createAndAddVBoxForCreditWords(_score);
vbox->add(t);
}
else if (_wordsText != "" || _rehearsalText != "" || _metroText != "") {
TextBase* t = 0;
if (_tpoSound > 0.1) {
// to prevent duplicates, only create a TempoText if none is present yet
Expand Down Expand Up @@ -2919,6 +2929,19 @@ bool MusicXMLParserDirection::isLikelyFingering() const
&& _tpoSound < 0.1;
}

//---------------------------------------------------------
// isLikelyCredit
//---------------------------------------------------------

bool MusicXMLParserDirection::isLikelyCredit(const Fraction& tick) const
{
return (tick + _offset < Fraction(5, 1)) // Only early in the piece
&& _rehearsalText == ""
&& _metroText == ""
&& _tpoSound < 0.1
&& _wordsText.contains(QRegularExpression("((Words|Music|Lyrics).*)+by\\s+([A-Z][a-zA-Z'’-]+\\s[A-Z][a-zA-Z'’-]+.*)+"));
}

//---------------------------------------------------------
// MusicXMLInferredFingering
//---------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions importexport/musicxml/importmxmlpass2.h
Expand Up @@ -399,6 +399,7 @@ class MusicXMLParserDirection {
void handleRepeats(Measure* measure, const int track, const Fraction tick);
QString matchRepeat() const;
bool isLikelyFingering() const;
bool isLikelyCredit(const Fraction& tick) const;
void skipLogCurrElem();
};

Expand Down
192 changes: 192 additions & 0 deletions mtest/musicxml/io/testInferredSubtitle.xml
@@ -0,0 +1,192 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 3.1 Partwise//EN" "http://www.musicxml.org/dtds/partwise.dtd">
<score-partwise version="3.1">
<work>
<work-title>Inferred Subtitle</work-title>
</work>
<identification>
<creator type="composer">Henry Ives</creator>
<encoding>
<software>MuseScore 0.7.0</software>
<encoding-date>2007-09-10</encoding-date>
<supports element="accidental" type="yes"/>
<supports element="beam" type="yes"/>
<supports element="print" attribute="new-page" type="no"/>
<supports element="print" attribute="new-system" type="no"/>
<supports element="stem" type="yes"/>
</encoding>
</identification>
<defaults>
<scaling>
<millimeters>7</millimeters>
<tenths>40</tenths>
</scaling>
<page-layout>
<page-height>1697.14</page-height>
<page-width>1200</page-width>
<page-margins type="even">
<left-margin>85.7143</left-margin>
<right-margin>85.7143</right-margin>
<top-margin>85.7143</top-margin>
<bottom-margin>85.7143</bottom-margin>
</page-margins>
<page-margins type="odd">
<left-margin>85.7143</left-margin>
<right-margin>85.7143</right-margin>
<top-margin>85.7143</top-margin>
<bottom-margin>85.7143</bottom-margin>
</page-margins>
</page-layout>
<word-font font-family="Edwin" font-size="10"/>
<lyric-font font-family="Edwin" font-size="10"/>
</defaults>
<credit page="1">
<credit-type>title</credit-type>
<credit-words default-x="600" default-y="1611.43" justify="center" valign="top" font-size="22">Inferred Subtitle</credit-words>
</credit>
<part-list>
<part-group type="start" number="1">
<group-symbol>brace</group-symbol>
</part-group>
<score-part id="P1">
<part-name>Piano</part-name>
<part-abbreviation>Pno.</part-abbreviation>
<score-instrument id="P1-I1">
<instrument-name>Piano</instrument-name>
</score-instrument>
<midi-device id="P1-I1" port="1"></midi-device>
<midi-instrument id="P1-I1">
<midi-channel>1</midi-channel>
<midi-program>1</midi-program>
<volume>78.7402</volume>
<pan>0</pan>
</midi-instrument>
</score-part>
</part-list>
<part id="P1">
<measure number="1" width="293.97">
<print>
<system-layout>
<system-margins>
<left-margin>50.00</left-margin>
<right-margin>0.00</right-margin>
</system-margins>
<top-system-distance>170.00</top-system-distance>
</system-layout>
</print>
<attributes>
<divisions>2</divisions>
<key>
<fifths>0</fifths>
</key>
<time>
<beats>4</beats>
<beat-type>4</beat-type>
</time>
<clef>
<sign>G</sign>
<line>2</line>
</clef>
</attributes>
<direction placement="above">
<direction-type>
<words relative-y="10.00">Words and Music by Henry Ives</words>
</direction-type>
</direction>
<note default-x="80.72" default-y="-15.00">
<pitch>
<step>C</step>
<octave>5</octave>
</pitch>
<duration>1</duration>
<voice>1</voice>
<type>eighth</type>
<stem>down</stem>
<beam number="1">begin</beam>
<lyric number="1" default-x="6.50" default-y="-44.91" relative-y="-30.00">
<syllabic>begin</syllabic>
<text>ha</text>
</lyric>
</note>
<note default-x="117.18" default-y="-15.00">
<pitch>
<step>C</step>
<octave>5</octave>
</pitch>
<duration>1</duration>
<voice>1</voice>
<type>eighth</type>
<stem>down</stem>
<beam number="1">end</beam>
<lyric number="1" default-x="6.50" default-y="-44.91" relative-y="-30.00">
<syllabic>end</syllabic>
<text>ha</text>
</lyric>
</note>
<note>
<rest/>
<duration>2</duration>
<voice>1</voice>
<type>quarter</type>
</note>
<note>
<rest/>
<duration>4</duration>
<voice>1</voice>
<type>half</type>
</note>
</measure>
<measure number="2" width="202.30">
<note default-x="26.30" default-y="-45.00">
<pitch>
<step>D</step>
<octave>4</octave>
</pitch>
<duration>2</duration>
<voice>1</voice>
<type>quarter</type>
<stem>up</stem>
<lyric number="1" default-x="8.72" default-y="-44.91" relative-y="-30.00">
<syllabic>single</syllabic>
<text>nice.</text>
</lyric>
</note>
<note>
<rest/>
<duration>2</duration>
<voice>1</voice>
<type>quarter</type>
</note>
<note>
<rest/>
<duration>4</duration>
<voice>1</voice>
<type>half</type>
</note>
</measure>
<measure number="3" width="160.22">
<note>
<rest measure="yes"/>
<duration>8</duration>
<voice>1</voice>
</note>
</measure>
<measure number="4" width="160.22">
<note>
<rest measure="yes"/>
<duration>8</duration>
<voice>1</voice>
</note>
</measure>
<measure number="5" width="161.86">
<note>
<rest measure="yes"/>
<duration>8</duration>
<voice>1</voice>
</note>
<barline location="right">
<bar-style>light-heavy</bar-style>
</barline>
</measure>
</part>
</score-partwise>

0 comments on commit 51c73cc

Please sign in to comment.