Skip to content

Commit

Permalink
fix #98136 - [MusicXML import] extra instrument when importing multi-…
Browse files Browse the repository at this point in the history
…instrument part starting with rest(s)
  • Loading branch information
lvinken committed Feb 14, 2016
1 parent 2b277f6 commit 14e550c
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 35 deletions.
26 changes: 25 additions & 1 deletion mscore/importmxmlpass1.cpp
Expand Up @@ -263,6 +263,8 @@ void MusicXMLParserPass1::initPartState(const QString& /* partId */)
{
_timeSigDura = Fraction(0, 0); // invalid
_octaveShifts.clear();
_firstInstrSTime = Fraction(0, 1);
_firstInstrId = "";
}

//---------------------------------------------------------
Expand Down Expand Up @@ -1919,6 +1921,9 @@ void MusicXMLParserPass1::part()
allocateVoices(_parts[id].voicelist);
// calculate the octave shifts
_parts[id].calcOctaveShifts();
// set first instrument for multi-instrument part starting with rest
if (_firstInstrId != "" && _firstInstrSTime > Fraction(0, 1))
_parts[id]._instrList.setInstrument(_firstInstrId, Fraction(0, 1));

// debug: print results
/*
Expand Down Expand Up @@ -2614,6 +2619,24 @@ void MusicXMLParserPass1::handleOctaveShift(const Fraction cTime,
desc = MxmlOctaveShiftDesc(tp, sz, cTime);
}

//---------------------------------------------------------
// setFirstInstr
//---------------------------------------------------------

void MusicXMLParserPass1::setFirstInstr(const QString& id, const Fraction stime)
{
// check for valid arguments
if (id == "" || !stime.isValid() || stime < Fraction(0, 1))
return;

// check for no instrument found yet or new earliest start time
// note: compare using <= to catch instrument at t=0
if (_firstInstrId == "" || stime <= _firstInstrSTime) {
_firstInstrId = id;
_firstInstrSTime = stime;
}
}

//---------------------------------------------------------
// note
//---------------------------------------------------------
Expand Down Expand Up @@ -2699,10 +2722,11 @@ void MusicXMLParserPass1::note(const QString& partId,
staff--;

// multi-instrument handling
setFirstInstr(instrId, sTime);
QString prevInstrId = _parts[partId]._instrList.instrument(sTime);
bool mustInsert = instrId != prevInstrId;
/*
qDebug("tick %s (%d) staff %d voice '%s' previnst='%s' instrument '%s' insert %d",
qDebug("tick %s (%d) staff %d voice '%s' previnst='%s' instrument '%s' mustInsert %d",
qPrintable(sTime.print()),
sTime.ticks(),
staff + 1,
Expand Down
6 changes: 5 additions & 1 deletion mscore/importmxmlpass1.h
Expand Up @@ -99,8 +99,10 @@ class MusicXMLParserPass1 {
int octaveShift(const QString& id, const int staff, const Fraction f) const;

private:
// generic pass 1 data
// functions
void setFirstInstr(const QString& id, const Fraction stime);

// generic pass 1 data
QXmlStreamReader _e;
int _divs; ///< Current MusicXML divisions value
QMap<QString, MusicXmlPart> _parts; ///< Parts data, mapped on part id
Expand All @@ -114,6 +116,8 @@ class MusicXMLParserPass1 {
// part specific data (TODO: move to part-specific class)
Fraction _timeSigDura; ///< Measure duration according to last timesig read
QMap<int, MxmlOctaveShiftDesc> _octaveShifts; ///< Pending octave-shifts
Fraction _firstInstrSTime; ///< First instrument start time
QString _firstInstrId; ///< First instrument id
};

} // namespace Ms
Expand Down
71 changes: 43 additions & 28 deletions mscore/importmxmlpass2.cpp
Expand Up @@ -531,38 +531,53 @@ static QString findDeleteStaffText(Segment* s, int track)
static void setPartInstruments(Part* part, const QString& partId,
Score* score, const MusicXmlInstrList& il, const MusicXMLDrumset& mxmlDrumset)
{
QString prevInstrId;
for (auto it = il.cbegin(); it != il.cend(); ++it) {
Fraction f = (*it).first;
if (f > Fraction(0, 1)) {
if (f == Fraction(0, 1))
prevInstrId = (*it).second; // instrument id at t = 0
else if (f > Fraction(0, 1)) {
auto instrId = (*it).second;
int staff = score->staffIdx(part);
int track = staff * VOICES;
//qDebug("setPartInstruments: instrument change: tick %s (%d) track %d instr '%s'",
// qPrintable(f.print()), f.ticks(), track, qPrintable(instrId));
Segment* segment = score->tick2segment(f.ticks(), true, Segment::Type::ChordRest, true);
if (!segment)
qDebug("setPartInstruments: segment for instrument change at tick %d not found", f.ticks()); // TODO
else if (!mxmlDrumset.contains(instrId))
qDebug("setPartInstruments: changed instrument '%s' at tick %d not found in part '%s'",
qPrintable(instrId), f.ticks(), qPrintable(partId)); // TODO
else {
MusicXMLDrumInstrument mxmlInstr = mxmlDrumset.value(instrId);
Instrument instr;
instr.channel(0)->program = mxmlInstr.midiProgram;
instr.channel(0)->pan = mxmlInstr.midiPan;
instr.channel(0)->volume = mxmlInstr.midiVolume;
instr.setTrackName(mxmlInstr.name);
InstrumentChange* ic = new InstrumentChange(instr, score);
ic->setTrack(track);
// if there is already a staff text at this tick / track,
// delete it and use its text here instead of "Instrument"
QString text = findDeleteStaffText(segment, track);
ic->setXmlText(text.isEmpty() ? "Instrument" : text);
segment->add(ic);

int key = part->instruments()->rbegin()->first;
part->setMidiChannel(mxmlInstr.midiChannel, mxmlInstr.midiPort, key);
bool mustInsert = instrId != prevInstrId;
/*
qDebug("setPartInstruments: f %s previd %s id %s mustInsert %d",
qPrintable(f.print()),
qPrintable(prevInstrId),
qPrintable(instrId),
mustInsert);
*/
if (mustInsert) {
int staff = score->staffIdx(part);
int track = staff * VOICES;
qDebug("setPartInstruments: instrument change: tick %s (%d) track %d instr '%s'",
qPrintable(f.print()), f.ticks(), track, qPrintable(instrId));
Segment* segment = score->tick2segment(f.ticks(), true, Segment::Type::ChordRest, true);
if (!segment)
qDebug("setPartInstruments: segment for instrument change at tick %d not found", f.ticks()); // TODO
else if (!mxmlDrumset.contains(instrId))
qDebug("setPartInstruments: changed instrument '%s' at tick %d not found in part '%s'",
qPrintable(instrId), f.ticks(), qPrintable(partId)); // TODO
else {
MusicXMLDrumInstrument mxmlInstr = mxmlDrumset.value(instrId);
Instrument instr;
qDebug("setPartInstruments: instr %p", &instr);
instr.channel(0)->program = mxmlInstr.midiProgram;
instr.channel(0)->pan = mxmlInstr.midiPan;
instr.channel(0)->volume = mxmlInstr.midiVolume;
instr.setTrackName(mxmlInstr.name);
InstrumentChange* ic = new InstrumentChange(instr, score);
ic->setTrack(track);
// if there is already a staff text at this tick / track,
// delete it and use its text here instead of "Instrument"
QString text = findDeleteStaffText(segment, track);
ic->setXmlText(text.isEmpty() ? "Instrument" : text);
segment->add(ic);

int key = part->instruments()->rbegin()->first;
part->setMidiChannel(mxmlInstr.midiChannel, mxmlInstr.midiPort, key);
}
}
prevInstrId = instrId;
}
}
}
Expand Down
4 changes: 0 additions & 4 deletions mtest/musicxml/io/testMultiInstrumentPart2.xml
Expand Up @@ -192,15 +192,13 @@
<note>
<rest/>
<duration>4</duration>
<instrument id="P2-I1"/>
<voice>1</voice>
</note>
</measure>
<measure number="2">
<note>
<rest/>
<duration>4</duration>
<instrument id="P2-I1"/>
<voice>1</voice>
</note>
</measure>
Expand All @@ -213,15 +211,13 @@
<note>
<rest/>
<duration>4</duration>
<instrument id="P2-I1"/>
<voice>1</voice>
</note>
</measure>
<measure number="4">
<note>
<rest/>
<duration>4</duration>
<instrument id="P2-I1"/>
<voice>1</voice>
</note>
</measure>
Expand Down
2 changes: 1 addition & 1 deletion mtest/musicxml/io/tst_mxml_io.cpp
Expand Up @@ -107,7 +107,7 @@ private slots:
void measureLength() { mxmlIoTestRef("testMeasureLength"); }
void midiPortExport() { mxmlMscxExportTestRef("testMidiPortExport"); }
void multiInstrumentPart1() { mxmlIoTest("testMultiInstrumentPart1"); }
//void multiInstrumentPart2() { mxmlIoTest("testMultiInstrumentPart2"); } must also fix exportxml.cpp
void multiInstrumentPart2() { mxmlIoTest("testMultiInstrumentPart2"); }
void multiMeasureRest1() { mxmlIoTestRef("testMultiMeasureRest1"); }
//void multiMeasureRest2() { mxmlIoTestRef("testMultiMeasureRest2"); } end repeat missing
void multiMeasureRest3() { mxmlIoTestRef("testMultiMeasureRest3"); }
Expand Down

0 comments on commit 14e550c

Please sign in to comment.