Skip to content

Commit

Permalink
fix #175226 - [MusicXML import] add instrument-sound to MIDI mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
lvinken committed Mar 7, 2017
1 parent 297b66f commit 161639f
Show file tree
Hide file tree
Showing 7 changed files with 366 additions and 5 deletions.
65 changes: 65 additions & 0 deletions mscore/importmxmlpass1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
//=============================================================================

#include "libmscore/box.h"
#include "libmscore/instrtemplate.h"
#include "libmscore/measure.h"
#include "libmscore/page.h"
#include "libmscore/part.h"
Expand Down Expand Up @@ -1686,6 +1687,46 @@ void MusicXMLParserPass1::partGroup(const int scoreParts,
qPrintable(type)); // TODO
}

//---------------------------------------------------------
// findInstrument
//---------------------------------------------------------

/**
Find the first InstrumentTemplate with musicXMLid instrSound
and a non-empty set of channels.
*/

static const InstrumentTemplate* findInstrument(const QString& instrSound)
{
const InstrumentTemplate* instr = nullptr;

for (const InstrumentGroup* group : instrumentGroups) {
for (const InstrumentTemplate* templ : group->instrumentTemplates) {
if (templ->musicXMLid == instrSound && !templ->channel.isEmpty()) {
return templ;
}
}
}
return instr;
}

//---------------------------------------------------------
// fixupMidiProgram
//---------------------------------------------------------

static void fixupMidiProgram(MusicXMLDrumset& drumset)
{
for (auto& instr : drumset) {
if (instr.midiProgram < 0 && instr.sound != "") {
const InstrumentTemplate* templ = findInstrument(instr.sound);
if (templ) {
const int prog = templ->channel.at(0).program;
instr.midiProgram = prog;
}
}
}
}

//---------------------------------------------------------
// scorePart
//---------------------------------------------------------
Expand Down Expand Up @@ -1766,6 +1807,9 @@ void MusicXMLParserPass1::scorePart()
else
skipLogCurrElem();
}

fixupMidiProgram(_drumsets[id]);

Q_ASSERT(_e.isEndElement() && _e.name() == "score-part");
}

Expand Down Expand Up @@ -1804,6 +1848,27 @@ void MusicXMLParserPass1::scoreInstrument(const QString& partId)
if (_partMap[partId]->partName() == "")
_partMap[partId]->setPartName(instrName);
}
else if (_e.name() == "instrument-sound") {
QString instrSound = _e.readElementText();
if (_drumsets[partId].contains(instrId))
_drumsets[partId][instrId].sound = instrSound;
}
else if (_e.name() == "virtual-instrument") {
while (_e.readNextStartElement()) {
if (_e.name() == "virtual-library") {
QString virtualLibrary = _e.readElementText();
if (_drumsets[partId].contains(instrId))
_drumsets[partId][instrId].virtLib = virtualLibrary;
}
else if (_e.name() == "virtual-name") {
QString virtualName = _e.readElementText();
if (_drumsets[partId].contains(instrId))
_drumsets[partId][instrId].virtName = virtualName;
}
else
skipLogCurrElem();
}
}
else
skipLogCurrElem();
}
Expand Down
3 changes: 2 additions & 1 deletion mscore/musicxmlsupport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,14 @@ bool VoiceOverlapDetector::stavesOverlap(const QString& voice) const

QString MusicXMLDrumInstrument::toString() const
{
return QString("chan %1 prog %2 vol %3 pan %4 pitch %5 name %6 head %7 line %8 stemDir %9")
return QString("chan %1 prog %2 vol %3 pan %4 pitch %5 name '%6' sound '%7' head %8 line %9 stemDir %10")
.arg(midiChannel)
.arg(midiProgram)
.arg(midiVolume)
.arg(midiPan)
.arg(pitch)
.arg(name)
.arg(sound)
.arg(int(notehead))
.arg(line)
.arg(int(stemDirection));
Expand Down
11 changes: 7 additions & 4 deletions mscore/musicxmlsupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ class VoiceOverlapDetector {
struct MusicXMLDrumInstrument {
int pitch; // pitch read from MusicXML
QString name; // name read from MusicXML
QString sound; // sound read from MusicXML
QString virtLib; // virtual library read from MusicXML
QString virtName; // virtualname read from MusicXML
int midiChannel; // channel read from MusicXML
int midiPort; // port read from MusicXML
int midiProgram; // program read from MusicXML
Expand All @@ -142,13 +145,13 @@ struct MusicXMLDrumInstrument {

MusicXMLDrumInstrument()
: pitch(-1), name(), midiChannel(-1), midiPort(-1), midiProgram(-1), midiVolume(100), midiPan(63),
notehead(NoteHead::Group::HEAD_INVALID), line(0), stemDirection(Direction::AUTO) {}
notehead(NoteHead::Group::HEAD_INVALID), line(0), stemDirection(Direction::AUTO) {}
MusicXMLDrumInstrument(QString s)
: pitch(-1), name(s), midiChannel(-1), midiPort(-1), midiProgram(-1), midiVolume(100), midiPan(63),
notehead(NoteHead::Group::HEAD_INVALID), line(0), stemDirection(Direction::AUTO) {}
notehead(NoteHead::Group::HEAD_INVALID), line(0), stemDirection(Direction::AUTO) {}
MusicXMLDrumInstrument(int p, QString s, NoteHead::Group nh, int l, Direction d)
: pitch(p), name(s), midiChannel(-1), midiPort(-1), midiProgram(-1), midiVolume(100), midiPan(63),
notehead(nh), line(l), stemDirection(d) {}
notehead(nh), line(l), stemDirection(d) {}
};

/**
Expand All @@ -169,7 +172,7 @@ class MxmlSupport {
static Fraction durationAsFraction(const int divisions, const QDomElement e);
static Fraction noteTypeToFraction(QString type);
static Fraction calculateFraction(QString type, int dots, int normalNotes, int actualNotes);
};
};

//---------------------------------------------------------
// ValidatorMessageHandler
Expand Down
146 changes: 146 additions & 0 deletions mtest/musicxml/io/testInstrumentSound.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 3.0 Partwise//EN" "http://www.musicxml.org/dtds/partwise.dtd">
<score-partwise>
<work>
<work-number>MuseScore testfile</work-number>
<work-title>Instrument-sound</work-title>
</work>
<identification>
<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>
<miscellaneous>
<miscellaneous-field name="description">
Check handling of instruments without MIDI info but with instrument-sound
and virtual-instrument, as is produced by Sibelius 7 (Direct export).
Expected difference: instrument-sound and virtual-instrument replaced by
midi-device and midi-instrument.
</miscellaneous-field>
</miscellaneous>
</identification>
<part-list>
<score-part id="P1">
<part-name>Guitar</part-name>
<part-abbreviation>Gtr.</part-abbreviation>
<score-instrument id="P1-I1">
<instrument-name>Guitar</instrument-name>
<instrument-sound>pluck.guitar.nylon-string</instrument-sound>
<virtual-instrument>
<virtual-library>General MIDI</virtual-library>
<virtual-name>Acoustic Guitar (nylon)</virtual-name>
</virtual-instrument>
</score-instrument>
</score-part>
<score-part id="P2">
<part-name>Bandoneon</part-name>
<part-abbreviation>Band.</part-abbreviation>
<score-instrument id="P2-I1">
<instrument-name>Accordion</instrument-name>
<instrument-sound>keyboard.bandoneon</instrument-sound>
<virtual-instrument>
<virtual-library>General MIDI</virtual-library>
<virtual-name>Tango Accordion</virtual-name>
</virtual-instrument>
</score-instrument>
</score-part>
<score-part id="P3">
<part-name>Contrabass</part-name>
<part-abbreviation>Cb.</part-abbreviation>
<score-instrument id="P3-I1">
<instrument-name>Contrabass</instrument-name>
<instrument-sound>strings.contrabass</instrument-sound>
<virtual-instrument>
<virtual-library>General MIDI</virtual-library>
<virtual-name>Contrabass</virtual-name>
</virtual-instrument>
</score-instrument>
</score-part>
</part-list>
<part id="P1">
<measure number="1">
<attributes>
<divisions>1</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>
<note>
<pitch>
<step>C</step>
<octave>4</octave>
</pitch>
<duration>4</duration>
<voice>1</voice>
<type>whole</type>
</note>
</measure>
</part>
<part id="P2">
<measure number="1">
<attributes>
<divisions>1</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>
<note>
<pitch>
<step>C</step>
<octave>4</octave>
</pitch>
<duration>4</duration>
<voice>1</voice>
<type>whole</type>
</note>
</measure>
</part>
<part id="P3">
<measure number="1">
<attributes>
<divisions>1</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>
<note>
<pitch>
<step>C</step>
<octave>4</octave>
</pitch>
<duration>4</duration>
<voice>1</voice>
<type>whole</type>
</note>
</measure>
</part>
</score-partwise>
Loading

0 comments on commit 161639f

Please sign in to comment.